diff --git a/Makefile.am b/Makefile.am
index 5327646..12decd3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,7 @@ SRC_FILES += $(ECUTOOLS_SRC_FILES)
#LOG_FLAGS += -DIOT_WARN
#LOG_FLAGS += -DIOT_ERROR
-COMPILER_FLAGS = -g3
+COMPILER_FLAGS = -g3 -w
COMPILER_FLAGS += $(LOG_FLAGS)
# ecutools
diff --git a/README.md b/README.md
index 97268a0..27d04d2 100755
--- a/README.md
+++ b/README.md
@@ -55,11 +55,11 @@ Dynamic libraries (not included):
To install,
- ./autogen.sh
- ./configure
+ ./autogen.sh
+ ./configure
make mbedtls
- make
- sudo make install
+ make
+ sudo make install
## Development
diff --git a/bindings/ruby/lib/ecutools/j2534.rb b/bindings/ruby/lib/ecutools/j2534.rb
index c6009a1..af14083 100644
--- a/bindings/ruby/lib/ecutools/j2534.rb
+++ b/bindings/ruby/lib/ecutools/j2534.rb
@@ -50,13 +50,13 @@ def PassThruOpen(name, deviceId)
pDeviceId = FFI::MemoryPointer.new(:ulong, 8).put_ulong(0, deviceId)
response = Libj2534.PassThruOpen(pName, pDeviceId)
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
- true
+ response
end
def PassThruClose(deviceId)
response = Libj2534.PassThruClose(deviceId)
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
- true
+ response
end
def PassThruConnect(deviceId, protocolId, flags, baudRate, resource, channelId)
@@ -68,13 +68,13 @@ def PassThruConnect(deviceId, protocolId, flags, baudRate, resource, channelId)
pChannelID = FFI::MemoryPointer.new(:ulong, 8).put_ulong(0, channelId)
response = Libj2534.PassThruConnect(deviceId, protocolId, flags, baudRate, resourceStruct, pChannelID)
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
- true
+ response
end
def PassThruDisconnect(channelId)
response = Libj2534.PassThruDisconnect(channelId)
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
- true
+ response
end
def PassThruLogicalConnect(physicalChannelId, protocolId, flags, channelDescriptor, channelId)
@@ -92,7 +92,47 @@ def PassThruSelect(channelSet, selectType, timeout)
).put_array_of_ulong(0, channelSet.ChannelList)
response = Libj2534.PassThruSelect(channelset, selectType, timeout)
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
- true
+ response
+ end
+
+ def PassThruReadMsgs(channelId, message, numMsgs, timeout)
+ end
+
+ def PassThruQueueMsgs(channelId, message, numMsgs)
+ end
+
+ def PassThruStartPeriodicMsg(channelId, message, messageId, timeInterval)
+ end
+
+ def PassThruStopPeriodicMsg(channelId, messageId)
+ end
+
+ # long PassThruStartMsgFilter(unsigned long ChannelID, unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg, unsigned long *pFilterID);
+
+ # attach_function :PassThruStartMsgFilter, [ :ulong, :ulong, Ecutools::J2534::Structs::PASSTHRU_MSG.by_ref, Ecutools::J2534::Structs::PASSTHRU_MSG.by_ref, :pointer ], :long
+
+ def PassThruStartMsgFilter(channelId, filterType, maskMsg, patternMsg, filterId)
+ pMaskMsg = map_model_to_passthru_msg(maskMsg, Ecutools::J2534::Structs::PASSTHRU_MSG.new)
+ pPatternMsg = map_model_to_passthru_msg(patternMsg, Ecutools::J2534::Structs::PASSTHRU_MSG.new)
+ pFilterID = FFI::MemoryPointer.new(:ulong, 8).put_ulong(0, filterId)
+ response = Libj2534.PassThruStartMsgFilter(channelId, filterType, pMaskMsg, pPatternMsg, pFilterID)
+ raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
+ response
+ end
+
+ def PassThruStopMsgFilter(channelId, filterId)
+ end
+
+ def PassThruSetProgrammingVoltage(deviceId, resourceStruct, voltage)
+ end
+
+ def PassThruReadVersion(deviceId)
+ end
+
+ def PassThruGetLastError
+ end
+
+ def PassThruIoctl(controlTarget, ioctlId)
end
private
@@ -108,5 +148,18 @@ def map_sdevice_to_model(sdevice, device)
device
end
+ def map_model_to_passthru_msg(model, passthru_msg)
+ passthru_msg[:ProtocolID] = model.ProtocolID || 0
+ passthru_msg[:MsgHandle] = model.MsgHandle
+ passthru_msg[:RxStatus] = model.RxStatus || 0
+ passthru_msg[:TxFlags] = model.TxFlags || 0
+ passthru_msg[:Timestamp] = model.Timestamp || 0
+ passthru_msg[:DataLength] = model.DataLength
+ passthru_msg[:ExtraDataIndex] = model.ExtraDataIndex || 0
+ passthru_msg[:DataBuffer] = model.DataBuffer
+ passthru_msg[:DataBufferSize] = model.DataBufferSize || 0
+ passthru_msg
+ end
+
end
end
diff --git a/bindings/ruby/spec/PassThruConnect_STATUS_NOERROR_integration_spec.rb b/bindings/ruby/spec/PassThruConnect_STATUS_NOERROR_integration_spec.rb
index 1f36373..944f28b 100644
--- a/bindings/ruby/spec/PassThruConnect_STATUS_NOERROR_integration_spec.rb
+++ b/bindings/ruby/spec/PassThruConnect_STATUS_NOERROR_integration_spec.rb
@@ -23,10 +23,17 @@
it 'returns STATUS_NOERROR when connected' do
things.test_with_ecutuned {
- expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(true)
+ expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(Ecutools::J2534::Error::STATUS_NOERROR)
resource = Ecutools::J2534::Models::Resource.new
resource.Connector = Ecutools::J2534::J1962_CONNECTOR
- expect(j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)).to eq(true)
+ expect(j2534.PassThruConnect(
+ 1,
+ Ecutools::J2534::CAN,
+ Ecutools::J2534::CAN_ID_BOTH,
+ 500000,
+ resource,
+ 1
+ )).to eq(Ecutools::J2534::Error::STATUS_NOERROR)
}
end
diff --git a/bindings/ruby/spec/PassThruDisconnect_STATUS_NOERROR_integration_spec.rb b/bindings/ruby/spec/PassThruDisconnect_STATUS_NOERROR_integration_spec.rb
index 9eea54d..65a5da2 100644
--- a/bindings/ruby/spec/PassThruDisconnect_STATUS_NOERROR_integration_spec.rb
+++ b/bindings/ruby/spec/PassThruDisconnect_STATUS_NOERROR_integration_spec.rb
@@ -24,13 +24,19 @@
it 'returns STATUS_NOERROR when disconnected' do
things.test_with_ecutuned {
- expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(true)
+ expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(Ecutools::J2534::Error::STATUS_NOERROR)
resource = Ecutools::J2534::Models::Resource.new
resource.Connector = Ecutools::J2534::J1962_CONNECTOR
- expect(j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)).to eq(true)
-
- expect(j2534.PassThruDisconnect(1)).to eq(true)
+ expect(j2534.PassThruConnect(
+ 1,
+ Ecutools::J2534::CAN,
+ Ecutools::J2534::CAN_ID_BOTH, 500000,
+ resource,
+ 1
+ )).to eq(Ecutools::J2534::Error::STATUS_NOERROR)
+
+ expect(j2534.PassThruDisconnect(1)).to eq(Ecutools::J2534::Error::STATUS_NOERROR)
}
end
diff --git a/bindings/ruby/spec/PassThruStartMsgFilter_ERR_EXCEEDED_LIMIT_integration_spec.rb b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_EXCEEDED_LIMIT_integration_spec.rb
new file mode 100644
index 0000000..0c21e1b
--- /dev/null
+++ b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_EXCEEDED_LIMIT_integration_spec.rb
@@ -0,0 +1,58 @@
+##
+# ecutools: IoT Automotive Tuning, Diagnostics & Analytics
+# Copyright (C) 2014 Jeremy Hahn
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+require 'spec_helper'
+
+describe Ecutools::J2534 do
+ include_context 'J2534' do
+ context 'PassThruSelect' do
+
+ it 'returns ERR_EXCEEDED_LIMIT when more than 10 filters are specified' do
+ things.test_with_ecutuned {
+
+ expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(true)
+
+ resource = Ecutools::J2534::Models::Resource.new
+ resource.Connector = Ecutools::J2534::J1962_CONNECTOR
+ expect(j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)).to eq(true)
+
+ maskMsg = Ecutools::J2534::Models::Message.new
+ maskMsg.ProtocolID = Ecutools::J2534::CAN
+ maskMsg.MsgHandle = 1
+ maskMsg.DataBuffer = 0x7FF
+ maskMsg.DataLength = 11
+
+ patternMsg = Ecutools::J2534::Models::Message.new
+ patternMsg.ProtocolID = Ecutools::J2534::CAN
+ patternMsg.MsgHandle = 2
+ patternMsg.DataBuffer = 0x7DF
+ patternMsg.DataLength = 11
+
+ i = 0
+ 10.times do
+ i = i + 1
+ expect(j2534.PassThruStartMsgFilter(i, Ecutools::J2534::PASS_FILTER, maskMsg, patternMsg, 1)).to eq(true)
+ end
+ expect{j2534.PassThruStartMsgFilter(11, Ecutools::J2534::PASS_FILTER, maskMsg, patternMsg, 1)}.to raise_error /ERR_EXCEEDED_LIMIT/
+ }
+ end
+
+ end
+
+ end
+
+end
diff --git a/bindings/ruby/spec/PassThruStartMsgFilter_ERR_FILTER_TYPE_NOT_SUPPORTED_integration_spec.rb b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_FILTER_TYPE_NOT_SUPPORTED_integration_spec.rb
new file mode 100644
index 0000000..eb34546
--- /dev/null
+++ b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_FILTER_TYPE_NOT_SUPPORTED_integration_spec.rb
@@ -0,0 +1,53 @@
+##
+# ecutools: IoT Automotive Tuning, Diagnostics & Analytics
+# Copyright (C) 2014 Jeremy Hahn
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+require 'spec_helper'
+
+describe Ecutools::J2534 do
+ include_context 'J2534' do
+ context 'PassThruSelect' do
+
+ it 'returns ERR_FILTER_TYPE_NOT_SUPPORTED when an invalid filter is specified' do
+ things.test_with_ecutuned {
+
+ expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(true)
+
+ resource = Ecutools::J2534::Models::Resource.new
+ resource.Connector = Ecutools::J2534::J1962_CONNECTOR
+ expect(j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)).to eq(true)
+
+ maskMsg = Ecutools::J2534::Models::Message.new
+ maskMsg.ProtocolID = Ecutools::J2534::CAN
+ maskMsg.MsgHandle = 1
+ maskMsg.DataBuffer = 0x7FF
+ maskMsg.DataLength = 11
+
+ patternMsg = Ecutools::J2534::Models::Message.new
+ patternMsg.ProtocolID = Ecutools::J2534::CAN
+ patternMsg.MsgHandle = 2
+ patternMsg.DataBuffer = 0x7DF
+ patternMsg.DataLength = 11
+
+ expect{j2534.PassThruStartMsgFilter(1, 1, maskMsg, patternMsg, 1)}.to raise_error /ERR_FILTER_TYPE_NOT_SUPPORTED/
+ }
+ end
+
+ end
+
+ end
+
+end
diff --git a/bindings/ruby/spec/PassThruStartMsgFilter_ERR_INVALID_MSG_integration_spec.rb b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_INVALID_MSG_integration_spec.rb
new file mode 100644
index 0000000..39da686
--- /dev/null
+++ b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_INVALID_MSG_integration_spec.rb
@@ -0,0 +1,53 @@
+##
+# ecutools: IoT Automotive Tuning, Diagnostics & Analytics
+# Copyright (C) 2014 Jeremy Hahn
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+require 'spec_helper'
+
+describe Ecutools::J2534 do
+ include_context 'J2534' do
+ context 'PassThruSelect' do
+
+ it 'returns ERR_INVALID_MSG when an invalid data length is specified' do
+ things.test_with_ecutuned {
+
+ expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(true)
+
+ resource = Ecutools::J2534::Models::Resource.new
+ resource.Connector = Ecutools::J2534::J1962_CONNECTOR
+ expect(j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)).to eq(true)
+
+ maskMsg = Ecutools::J2534::Models::Message.new
+ maskMsg.ProtocolID = Ecutools::J2534::CAN
+ maskMsg.MsgHandle = 1
+ maskMsg.DataBuffer = 0x7FF
+ maskMsg.DataLength = 13
+
+ patternMsg = Ecutools::J2534::Models::Message.new
+ patternMsg.ProtocolID = Ecutools::J2534::CAN
+ patternMsg.MsgHandle = 2
+ patternMsg.DataBuffer = 0x7DF
+ patternMsg.DataLength = 13
+
+ expect{j2534.PassThruStartMsgFilter(1, Ecutools::J2534::PASS_FILTER, maskMsg, patternMsg, 1)}.to raise_error /ERR_INVALID_MSG/
+ }
+ end
+
+ end
+
+ end
+
+end
diff --git a/bindings/ruby/spec/PassThruStartMsgFilter_ERR_MSG_PROTOCOL_ID_integration_spec.rb b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_MSG_PROTOCOL_ID_integration_spec.rb
new file mode 100644
index 0000000..829ba38
--- /dev/null
+++ b/bindings/ruby/spec/PassThruStartMsgFilter_ERR_MSG_PROTOCOL_ID_integration_spec.rb
@@ -0,0 +1,53 @@
+##
+# ecutools: IoT Automotive Tuning, Diagnostics & Analytics
+# Copyright (C) 2014 Jeremy Hahn
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+require 'spec_helper'
+
+describe Ecutools::J2534 do
+ include_context 'J2534' do
+ context 'PassThruSelect' do
+
+ it 'returns ERR_MSG_PROTOCOL_ID when an invalid protocol id is specified' do
+ things.test_with_ecutuned {
+
+ expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(true)
+
+ resource = Ecutools::J2534::Models::Resource.new
+ resource.Connector = Ecutools::J2534::J1962_CONNECTOR
+ expect(j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)).to eq(true)
+
+ maskMsg = Ecutools::J2534::Models::Message.new
+ maskMsg.ProtocolID = 0
+ maskMsg.MsgHandle = 1
+ maskMsg.DataBuffer = 0x7FF
+ maskMsg.DataLength = 11
+
+ patternMsg = Ecutools::J2534::Models::Message.new
+ patternMsg.ProtocolID = 0
+ patternMsg.MsgHandle = 2
+ patternMsg.DataBuffer = 0x7DF
+ patternMsg.DataLength = 11
+
+ expect{j2534.PassThruStartMsgFilter(1, Ecutools::J2534::PASS_FILTER, maskMsg, patternMsg, 1)}.to raise_error /ERR_MSG_PROTOCOL_ID/
+ }
+ end
+
+ end
+
+ end
+
+end
diff --git a/bindings/ruby/spec/PassThruStartMsgFilter_STATUS_NOERROR_integration_spec.rb b/bindings/ruby/spec/PassThruStartMsgFilter_STATUS_NOERROR_integration_spec.rb
new file mode 100644
index 0000000..ab0fc4b
--- /dev/null
+++ b/bindings/ruby/spec/PassThruStartMsgFilter_STATUS_NOERROR_integration_spec.rb
@@ -0,0 +1,53 @@
+##
+# ecutools: IoT Automotive Tuning, Diagnostics & Analytics
+# Copyright (C) 2014 Jeremy Hahn
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+require 'spec_helper'
+
+describe Ecutools::J2534 do
+ include_context 'J2534' do
+ context 'PassThruSelect' do
+
+ it 'returns STATUS_NOERROR when a filter is successfully added' do
+ things.test_with_ecutuned {
+
+ expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(Ecutools::J2534::STATUS_NOERROR)
+
+ resource = Ecutools::J2534::Models::Resource.new
+ resource.Connector = Ecutools::J2534::J1962_CONNECTOR
+ expect(j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)).to eq(Ecutools::J2534::STATUS_NOERROR)
+
+ maskMsg = Ecutools::J2534::Models::Message.new
+ maskMsg.ProtocolID = Ecutools::J2534::CAN
+ maskMsg.MsgHandle = 1
+ maskMsg.DataBuffer = 0x7FF
+ maskMsg.DataLength = 11
+
+ patternMsg = Ecutools::J2534::Models::Message.new
+ patternMsg.ProtocolID = Ecutools::J2534::CAN
+ patternMsg.MsgHandle = 2
+ patternMsg.DataBuffer = 0x7DF
+ patternMsg.DataLength = 11
+
+ expect(j2534.PassThruStartMsgFilter(1, Ecutools::J2534::PASS_FILTER, maskMsg, patternMsg, 1)).to eq(Ecutools::J2534::STATUS_NOERROR)
+ }
+ end
+
+ end
+
+ end
+
+end
diff --git a/bindings/ruby/spec/spec_helper.rb b/bindings/ruby/spec/spec_helper.rb
index 4b5fd36..9c0988b 100644
--- a/bindings/ruby/spec/spec_helper.rb
+++ b/bindings/ruby/spec/spec_helper.rb
@@ -94,7 +94,7 @@ def test_with_ecutuned(&block)
rescue Errno::ENOMEM => nomem
puts "Garbage collecting to free up room for cleanup..."
GC.start
- sleep(5)
+ sleep(7)
`pkill -9 ecutuned`
`rm -rf /var/ecutools/cache/state_log`
end
diff --git a/cli/lib/ecutools/awsiot/service.rb b/cli/lib/ecutools/awsiot/service.rb
index 33ca2c2..b5c6f33 100644
--- a/cli/lib/ecutools/awsiot/service.rb
+++ b/cli/lib/ecutools/awsiot/service.rb
@@ -88,9 +88,7 @@ def list_things
Ecutools.aws.iot.list_things({
max_results: 100,
attribute_name: "type",
- attribute_value: "j2534",
- attribute_name: "acct",
- attribute_value: acct,
+ attribute_value: "j2534"
})[:things].map { |thing|
thing[:thing_name]
}
diff --git a/src/aws_iot_src/src/aws_iot_shadow.c b/src/aws_iot_src/src/aws_iot_shadow.c
index bb63c85..93ed0d7 100644
--- a/src/aws_iot_src/src/aws_iot_shadow.c
+++ b/src/aws_iot_src/src/aws_iot_shadow.c
@@ -63,7 +63,7 @@ IoT_Error_t aws_iot_shadow_init(AWS_IoT_Client *pClient, ShadowInitParameters_t
mqttInitParams.pRootCALocation = pParams->pRootCA;
mqttInitParams.pDeviceCertLocation = pParams->pClientCRT;
mqttInitParams.pDevicePrivateKeyLocation = pParams->pClientKey;
- mqttInitParams.mqttCommandTimeout_ms = 5000;
+ mqttInitParams.mqttCommandTimeout_ms = 7000;
mqttInitParams.tlsHandshakeTimeout_ms = 10000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = pParams->disconnectHandler;
diff --git a/src/awsiot_client.c b/src/awsiot_client.c
index 0abb940..2239c46 100755
--- a/src/awsiot_client.c
+++ b/src/awsiot_client.c
@@ -41,7 +41,7 @@ unsigned int awsiot_client_connect(awsiot_client *awsiot) {
mqttInitParams.pRootCALocation = rootCA;
mqttInitParams.pDeviceCertLocation = clientCRT;
mqttInitParams.pDevicePrivateKeyLocation = clientKey;
- mqttInitParams.mqttCommandTimeout_ms = 5000;
+ mqttInitParams.mqttCommandTimeout_ms = 7000;
mqttInitParams.tlsHandshakeTimeout_ms = 5000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = awsiot->ondisconnect;
@@ -114,9 +114,7 @@ unsigned int awsiot_client_unsubscribe(awsiot_client *awsiot, const char *topic)
unsigned int awsiot_client_publish(awsiot_client *awsiot, const char *topic, char *payload) {
- int payload_len = strlen(payload);// + 1;
-// payload[payload_len] = '\0';
-
+ int payload_len = strlen(payload);
syslog(LOG_DEBUG, "awsiot_client_publish: topic=%s, payload_len=%d, payload=%s", topic, payload_len, payload);
IoT_Publish_Message_Params paramsQOS0;
diff --git a/src/canbus.c b/src/canbus.c
index e533b75..bc32f94 100755
--- a/src/canbus.c
+++ b/src/canbus.c
@@ -176,6 +176,19 @@ unsigned int canbus_write(canbus_client *canbus, struct can_frame *frame) {
return bytes;
}
+int canbus_filter(canbus_client *canbus, struct can_filter *filters, unsigned int filter_len) {
+ if((canbus->state & CANBUS_STATE_CONNECTED) == 0) {
+ syslog(LOG_ERR, "canbus_write: CAN socket not connected");
+ return 1;
+ }
+ syslog(LOG_DEBUG, "canbus_filter: applying filters");
+ int i;
+ for(i=0; isocket, SOL_CAN_RAW, CAN_RAW_FILTER, filters, sizeof(struct can_filter) * filter_len);
+}
+
void canbus_shutdown(canbus_client *canbus, int how) {
if(canbus->socket != NULL) {
if(shutdown(canbus->socket, SHUT_RD) != 0) {
diff --git a/src/canbus.h b/src/canbus.h
index 2f61fa7..88977b6 100755
--- a/src/canbus.h
+++ b/src/canbus.h
@@ -58,6 +58,7 @@ unsigned int canbus_connect(canbus_client *canbus);
bool canbus_isconnected(canbus_client *canbus);
ssize_t canbus_read(canbus_client *canbus, struct can_frame *frame);
unsigned int canbus_write(canbus_client *canbus, struct can_frame *frame);
+int canbus_filter(canbus_client *canbus, struct can_filter *filters, unsigned int filter_len);
void canbus_shutdown(canbus_client *canbus, int how);
void canbus_close(canbus_client *canbus);
void canbus_framecpy(struct can_frame * frame, char *buf);
diff --git a/src/j2534.c b/src/j2534.c
index 22f5740..99b9d62 100755
--- a/src/j2534.c
+++ b/src/j2534.c
@@ -21,7 +21,7 @@
// not j2534 spec
static bool j2534_initialized = false;
static bool j2534_opened = false;
-static unsigned int j2534_current_api_call = 0;
+static unsigned long j2534_current_api_call = 0;
static long j2534_device_count = 0;
static char j2534_last_error[80] = {0};
static int *j2534_awsiot_error = NULL;
@@ -30,7 +30,7 @@ static SDEVICE j2534_device_list[25] = {0};
static vector j2534_client_vector;
static vector j2534_selected_channels;
-unsigned long unless_concurrent_call(unsigned long status, unsigned int api_call) {
+unsigned long unless_concurrent_call(unsigned long status, unsigned long api_call) {
syslog(LOG_DEBUG, "unless_concurrent_call: status=%x, api_call=%d", status, api_call);
if(j2534_current_api_call != api_call) {
strcpy(j2534_last_error, "ERR_CONCURRENT_API_CALL");
@@ -109,6 +109,45 @@ void j2534_onerror(awsiot_client *awsiot, const char *message) {
syslog(LOG_ERR, "j2534_onerror: message=%s", message);
}
+char *filter_json(j2534_client *client) {
+
+syslog(LOG_DEBUG, "filter_json: client->filters->count=%d", client->filters->count);
+
+ unsigned int json_len = client->filters->count * 27;
+ j2534_canfilter *canfilter = NULL;
+ char *json = malloc(sizeof(char) * json_len);
+ memset(json, '\0', sizeof(char) * json_len);
+ strcpy(json, "[");
+
+ int i;
+ for(i=0; ifilters->count; i++) {
+
+ char tmp_format[json_len];
+ char tmp[json_len];
+
+ canfilter = (j2534_canfilter *)vector_get(client->filters, i);
+
+ strcpy(tmp_format, "{\"id\":\"");
+ strcat(tmp_format, "%x");
+ strcat(tmp_format, "\",");
+ strcat(tmp_format, "\"mask\":\"");
+ strcat(tmp_format, "%x");
+ strcat(tmp_format, "\"}");
+
+ snprintf(tmp, json_len, tmp_format, canfilter->can_id, canfilter->can_mask);
+ strcat(json, tmp);
+
+ if(i < client->filters->count-1) {
+ strcat(json, ",");
+ }
+ }
+ strcat(json, "]");
+
+syslog(LOG_DEBUG, "filter_json: json=%s", json);
+
+ return json;
+}
+
unsigned int j2534_publish_state(j2534_client *client, int desired_state) {
char json_format[255] = "{\"state\":{\"desired\":{\"j2534\":{\"deviceId\":%i,\"state\":%i}}}}";
@@ -434,6 +473,7 @@ long PassThruOpen(const char *pName, unsigned long *pDeviceID) {
client->device = malloc(sizeof(SDEVICE));
client->deviceId = *pDeviceID;
+ client->protocolId = 0;
client->state = NULL;
client->awsiot = malloc(sizeof(awsiot_client));
@@ -450,6 +490,9 @@ long PassThruOpen(const char *pName, unsigned long *pDeviceID) {
vector_init(client->rxQueue);
vector_init(client->txQueue);
+ client->filters = malloc(sizeof(vector));
+ vector_init(client->filters);
+
client->channelSet = malloc(sizeof(SCHANNELSET));
client->channelSet->ChannelCount = 0;
client->channelSet->ChannelThreshold = 0;
@@ -549,6 +592,7 @@ long PassThruClose(unsigned long DeviceID) {
free(client->channelSet);
free(client->txQueue);
free(client->rxQueue);
+ free(client->filters);
free(client->name);
free(client->device);
free(client->awsiot);
@@ -658,6 +702,8 @@ long PassThruConnect(unsigned long DeviceID, unsigned long ProtocolID, unsigned
return unless_concurrent_call(ERR_INVALID_DEVICE_ID, J2534_PassThruConnect);
}
+ client->protocolId = ProtocolID;
+
/*
if(ProtocolID != J1850VPW && ProtocolID != J1850PWM && ProtocolID != ISO9141 &&
ProtocolID != ISO14230 && ProtocolID != CAN && ProtocolID != J2610 &&
@@ -1432,7 +1478,56 @@ long PassThruStopPeriodicMsg(unsigned long ChannelID, unsigned long MsgID) {
* STATUS_NOERROR Function call was successful
*/
long PassThruStartMsgFilter(unsigned long ChannelID, unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg, unsigned long *pFilterID) {
- return ERR_NOT_SUPPORTED;
+
+ j2534_current_api_call = J2534_PassThruStartMsgFilter;
+
+ if(pMaskMsg == NULL || pPatternMsg == NULL || pFilterID == NULL) {
+ return unless_concurrent_call(ERR_NULL_PARAMETER, J2534_PassThruStartMsgFilter);
+ }
+
+ if(!j2534_opened) {
+ return unless_concurrent_call(ERR_DEVICE_NOT_OPEN, J2534_PassThruStartMsgFilter);
+ }
+
+ j2534_client *client = j2534_client_by_channel_id(ChannelID);
+ if(client == NULL) {
+ return unless_concurrent_call(ERR_INVALID_DEVICE_ID, J2534_PassThruStartMsgFilter);
+ }
+
+ if(FilterType != PASS_FILTER && FilterType != BLOCK_FILTER) {
+ return unless_concurrent_call(ERR_FILTER_TYPE_NOT_SUPPORTED, J2534_PassThruStartMsgFilter);
+ }
+
+ if(pMaskMsg->ProtocolID != client->protocolId || pPatternMsg->ProtocolID != client->protocolId) {
+ return unless_concurrent_call(ERR_MSG_PROTOCOL_ID, J2534_PassThruStartMsgFilter);
+ }
+
+ if(pMaskMsg->DataLength < 1 || pMaskMsg->DataLength > 12) {
+ return unless_concurrent_call(ERR_INVALID_MSG, J2534_PassThruStartMsgFilter);
+ }
+
+ if(pPatternMsg->DataLength < 1 || pPatternMsg->DataLength > 12) {
+ return unless_concurrent_call(ERR_INVALID_MSG, J2534_PassThruStartMsgFilter);
+ }
+
+ if(client->filters->size >= 10) {
+ return unless_concurrent_call(ERR_EXCEEDED_LIMIT, J2534_PassThruStartMsgFilter);
+ }
+
+ j2534_canfilter *filter = malloc(sizeof(j2534_canfilter));
+ filter->id = pFilterID;
+ filter->can_id = pPatternMsg->DataBuffer;
+ filter->can_mask = pMaskMsg->DataBuffer;
+ vector_add(client->filters, filter);
+
+filter_json(client);
+
+return STATUS_NOERROR;
+
+ return unless_concurrent_call(
+ j2534_publish_state(client, J2534_PassThruStartMsgFilter),
+ J2534_PassThruStartMsgFilter
+ );
}
/**
diff --git a/src/j2534.h b/src/j2534.h
index 88659dd..4589ecc 100755
--- a/src/j2534.h
+++ b/src/j2534.h
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include "vector.h"
#include "passthru_thing.h"
#include "passthru_shadow_parser.h"
@@ -326,11 +327,18 @@ long PassThruIoctl(unsigned long ControlTarget, unsigned long IoctlID, void *Inp
#define J2534_PassThruGetLastError 18
#define J2534_PassThruIoctl 19
+typedef struct {
+ unsigned long *id;
+ canid_t can_id;
+ canid_t can_mask;
+} j2534_canfilter;
+
typedef struct {
char *name;
int *state;
unsigned long deviceId;
unsigned long channelId;
+ unsigned long protocolId;
bool opened;
char *shadow_update_topic;
char *shadow_update_accepted_topic;
@@ -338,11 +346,12 @@ typedef struct {
char *msg_rx_topic;
char *msg_tx_topic;
SDEVICE *device;
+ SCHANNELSET *channelSet;
awsiot_client *awsiot;
+ canbus_client *canbus;
vector *rxQueue;
vector *txQueue;
- SCHANNELSET *channelSet;
- canbus_client *canbus;
+ vector *filters;
} j2534_client;
void j2534_send_error(awsiot_client *awsiot, unsigned int error);
diff --git a/src/passthru_shadow.h b/src/passthru_shadow.h
index 1fb4218..d0e9e4d 100644
--- a/src/passthru_shadow.h
+++ b/src/passthru_shadow.h
@@ -36,7 +36,6 @@
#define PASSTHRU_SHADOW_GET_ACCEPTED_TOPIC "$aws/things/%s/shadow/get/accepted"
char DELTA_REPORT[SHADOW_MAX_SIZE_OF_RX_BUFFER];
-//bool messageArrivedOnDelta;
typedef struct {
int *type;
diff --git a/src/passthru_shadow_j2534_handler.c b/src/passthru_shadow_j2534_handler.c
index 64cb2c3..4cd6837 100644
--- a/src/passthru_shadow_j2534_handler.c
+++ b/src/passthru_shadow_j2534_handler.c
@@ -96,6 +96,7 @@ syslog(LOG_DEBUG, "passthru_shadow_j2534_handler_desired_open: j2534->deviceId=%
client = malloc(sizeof(j2534_client));
client->state = J2534_PassThruOpen;
client->deviceId = MYINT_DUP(j2534->deviceId);
+ client->opened = true;
unsigned int shadow_update_topic_len = PASSTHRU_SHADOW_UPDATE_TOPIC + strlen(client->name) + 1;
unsigned int shadow_update_accepted_topic_len = PASSTHRU_SHADOW_UPDATE_ACCEPTED_TOPIC + strlen(client->name) + 1;
@@ -211,46 +212,32 @@ void passthru_shadow_j2534_handler_desired_select(passthru_thing *thing, shadow_
void passthru_shadow_j2534_handler_desired_startMsgFilter(passthru_thing *thing, shadow_j2534 *j2534) {
- struct timeval start, stop;
- float milliseconds = 0;
-
- int can_frame_len = sizeof(struct can_frame);
- struct can_frame frame;
- memset(&frame, 0, can_frame_len);
-
- int data_len = can_frame_len + 25;
- char data[data_len];
- memset(data, 0, data_len);
+ int i;
j2534_client *client = passthru_shadow_j2534_handler_get_client(thing, j2534->deviceId);
if(client == NULL) {
- syslog(LOG_ERR, "passthru_shadow_j2534_handler_desired_startMsgFilter: unable to locate client: %s", j2534->deviceId);
return passthru_shadow_j2534_handler_send_error(thing, J2534_PassThruSelect, ERR_DEVICE_NOT_CONNECTED);
}
- client->state = J2534_PassThruStartMsgFilter;
- passthru_shadow_j2534_handler_send_report(J2534_PassThruStartMsgFilter);
+ if(!client->opened) {
+ return passthru_shadow_j2534_handler_send_error(thing, J2534_PassThruStartMsgFilter, ERR_DEVICE_NOT_OPEN);
+ }
- gettimeofday(&start, NULL);
- while(client->state == J2534_PassThruStartMsgFilter && milliseconds < J2534_TIMEOUT_MILLIS &&
- canbus_isconnected(client->canbus) && canbus_read(client->canbus, &frame) > 0) {
+ client->state = J2534_PassThruStartMsgFilter;
- canbus_framecpy(&frame, data);
- if(frame.can_id & CAN_ERR_FLAG) {
- syslog(LOG_ERR, "passthru_shadow_j2534_handler_desired_select: CAN ERROR: %s", data);
- continue;
- }
+ struct can_filter *filters = malloc(sizeof(struct can_filter) * client->filters->size);
- gettimeofday(&stop, NULL);
- milliseconds = (stop.tv_sec - start.tv_sec) * 1000.0f + (stop.tv_usec - start.tv_usec) / 1000.0f;
- syslog(LOG_DEBUG, "passthru_shadow_j2534_handler_desired_select: milliseconds=%f", milliseconds);
+ for(i=0; ifilters->count; i++) {
- if(awsiot_client_publish(client->awsiot, client->msg_rx_topic, data) != 0) {
- syslog(LOG_ERR, "passthru_shadow_j2534_handler_desired_select: failed to publish. topic=%s, rc=%d", client->msg_rx_topic, client->awsiot->rc);
- return passthru_shadow_j2534_handler_send_error(thing, J2534_PassThruSelect, client->awsiot->rc);
- }
+ j2534_canfilter *canfilter = (j2534_canfilter *)vector_get(client->filters, i);
+ filters[i].can_id = canfilter->can_id;
+ filters[i].can_mask = canfilter->can_mask;
}
+
+ canbus_filter(client->canbus, filters, client->filters->size);
+
+ passthru_shadow_j2534_handler_send_report(J2534_PassThruStartMsgFilter);
}
void passthru_shadow_j2534_handler_handle_desired_state(passthru_thing *thing, shadow_j2534 *j2534) {
@@ -279,6 +266,10 @@ void passthru_shadow_j2534_handler_handle_desired_state(passthru_thing *thing, s
return passthru_shadow_j2534_handler_desired_select(thing, j2534);
}
+ if(j2534->state == J2534_PassThruStartMsgFilter) {
+ return passthru_shadow_j2534_handler_desired_startMsgFilter(thing, j2534);
+ }
+
syslog(LOG_ERR, "passthru_shadow_j2534_handler_handle_desired_state: invalid state: %d", j2534->state);
}