Skip to content

Commit

Permalink
Get PassThruSelect working. Lots of supporing enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeremy Hahn committed Jun 10, 2016
1 parent 80ca261 commit 10fdf55
Show file tree
Hide file tree
Showing 33 changed files with 766 additions and 270 deletions.
4 changes: 2 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ ACLOCAL_AMFLAGS = -I m4
APP_DIR = src
APP_INCLUDE_DIRS = -I$(top_srcdir)/include -I$(APP_DIR)

ECUTOOLS_SRC_FILES = src/canbus.c src/awsiot_client.c src/mystring.c src/vector.c src/j2534.c src/j2534/apigateway.c
ECUTOOLS_SRC_FILES = src/canbus.c src/awsiot_client.c src/mystring.c src/myint.c src/vector.c src/j2534.c src/j2534/apigateway.c
ECUTOOLS_SRC_FILES += src/passthru_shadow.c src/passthru_shadow_state.c src/passthru_thing.c src/passthru_shadow_parser.c src/passthru_shadow_router.c
ECUTOOLS_SRC_FILES += src/passthru_shadow_connection_handler.c src/passthru_shadow_log_handler.c src/passthru_shadow_j2534_handler.c
ECUTOOLS_SRC_FILES += src/canbus_logger.c src/canbus_log.c src/canbus_filelogger.c src/canbus_awsiotlogger.c

J2534_SRC_FILES = src/awsiot_client.c src/passthru_shadow_parser.c src/j2534.c src/j2534/apigateway.c
J2534_SRC_FILES = src/awsiot_client.c src/passthru_shadow_parser.c src/j2534.c src/j2534/apigateway.c src/vector.c src/myint.c

ECUTOOLS_TEST_FILES = tests/check_j2534.c

Expand Down
30 changes: 24 additions & 6 deletions bindings/ruby/lib/ecutools/j2534.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module J2534
def PassThruScanForDevices
pDeviceCount = FFI::MemoryPointer.new(:ulong, 1)
response = Libj2534.PassThruScanForDevices(pDeviceCount)
raise Ecutools::J2534Error, Error[response] if response != 0
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
pDeviceCount.read_long
end

Expand All @@ -41,21 +41,21 @@ def PassThruGetNextDevice(device)
sdevice = Ecutools::J2534::Structs::SDEVICE.new
sdevice[:DeviceName].to_ptr.put_string(0, device.DeviceName) if device.DeviceName
response = Libj2534.PassThruGetNextDevice(sdevice)
raise Ecutools::J2534Error, Error[response] if response != 0
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
map_sdevice_to_model(sdevice, device)
end

def PassThruOpen(name, deviceId)
pName = FFI::MemoryPointer.from_string(name)
pDeviceId = FFI::MemoryPointer.new(:ulong, 8).put_ulong(0, deviceId)
response = Libj2534.PassThruOpen(pName, pDeviceId)
raise Ecutools::J2534Error, Error[response] unless response == 0
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
true
end

def PassThruClose(deviceId)
response = Libj2534.PassThruClose(deviceId)
raise Ecutools::J2534Error, Error[response] unless response == 0
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
true
end

Expand All @@ -67,13 +67,31 @@ def PassThruConnect(deviceId, protocolId, flags, baudRate, resource, channelId)
resourceStruct[:ResourceListPtr] = resource.ResourceListPtr || 0
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 == 0
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
true
end

def PassThruDisconnect(channelId)
response = Libj2534.PassThruDisconnect(channelId)
raise Ecutools::J2534Error, Error[response] unless response == 0
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
true
end

def PassThruLogicalConnect(physicalChannelId, protocolId, flags, channelDescriptor, channelId)
end

def PassThruLogicalDisconnect(channelId)
end

def PassThruSelect(channelSet, selectType, timeout)
channelset = Ecutools::J2534::Structs::SCHANNELSET.new
channelset[:ChannelCount] = channelSet.ChannelCount
channelset[:ChannelThreshold] = channelSet.ChannelThreshold
channelset[:ChannelList] = FFI::MemoryPointer.new(
:ulong, 8 * channelSet.ChannelList.length
).put_array_of_ulong(0, channelSet.ChannelList)
response = Libj2534.PassThruSelect(channelset, selectType, timeout)
raise Ecutools::J2534Error, Error[response] unless response === STATUS_NOERROR
true
end

Expand Down
13 changes: 13 additions & 0 deletions bindings/ruby/lib/ecutools/j2534/libj2534.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,17 @@ module Ecutools::J2534::Libj2534
attach_function :PassThruClose, [ :ulong ], :long
attach_function :PassThruConnect, [:ulong, :ulong, :ulong, :ulong, Ecutools::J2534::Structs::RESOURCE_STRUCT.by_value, :pointer ], :long
attach_function :PassThruDisconnect, [:ulong ], :long
attach_function :PassThruLogicalConnect, [ :ulong, :ulong, :ulong, :pointer, :pointer ], :long
attach_function :PassThruLogicalDisconnect, [ :ulong ], :long
attach_function :PassThruSelect, [ Ecutools::J2534::Structs::SCHANNELSET.by_ref, :ulong, :ulong ], :long
attach_function :PassThruReadMsgs, [ :ulong, Ecutools::J2534::Structs::PASSTHRU_MSG.by_ref, :pointer, :ulong ], :long
attach_function :PassThruQueueMsgs, [ :ulong, Ecutools::J2534::Structs::PASSTHRU_MSG.by_ref, :pointer ], :long
attach_function :PassThruStartPeriodicMsg, [ :ulong, Ecutools::J2534::Structs::PASSTHRU_MSG.by_ref, :pointer, :ulong ], :long
attach_function :PassThruStopPeriodicMsg, [ :ulong, :ulong ], :long
attach_function :PassThruStartMsgFilter, [ :ulong, :ulong, Ecutools::J2534::Structs::PASSTHRU_MSG.by_ref, Ecutools::J2534::Structs::PASSTHRU_MSG.by_ref, :pointer ], :long
attach_function :PassThruStopMsgFilter, [ :ulong, :ulong ], :long
attach_function :PassThruSetProgrammingVoltage, [ :ulong, Ecutools::J2534::Structs::RESOURCE_STRUCT.by_value, :ulong ], :long
attach_function :PassThruReadVersion, [ :ulong, :pointer, :pointer, :pointer ], :long
attach_function :PassThruGetLastError, [ :pointer ], :long
attach_function :PassThruIoctl, [ :ulong, :ulong, :pointer, :pointer ], :long
end
20 changes: 19 additions & 1 deletion bindings/ruby/lib/ecutools/j2534/models.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
module Ecutools::J2534::Models

class Device
attr_writer :DeviceName
attr_accessor :DeviceName
attr_accessor :DeviceAvailable
attr_accessor :DeviceDLLFWStatus
attr_accessor :DeviceConnectMedia
Expand All @@ -33,4 +33,22 @@ class Resource
attr_accessor :ResourceListPtr
end

class ChannelSet
attr_accessor :ChannelCount
attr_accessor :ChannelThreshold
attr_accessor :ChannelList
end

class Message
attr_accessor :ProtocolID
attr_accessor :MsgHandle
attr_accessor :RxStatus
attr_accessor :TxFlags
attr_accessor :Timestamp
attr_accessor :DataLength
attr_accessor :ExtraDataIndex
attr_accessor :DataBuffer
attr_accessor :DataBufferSize
end

end
18 changes: 18 additions & 0 deletions bindings/ruby/lib/ecutools/j2534/structs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,22 @@ class RESOURCE_STRUCT < FFI::Struct
:ResourceListPtr, :pointer
end

class SCHANNELSET < FFI::Struct
layout :ChannelCount, :ulong,
:ChannelThreshold, :ulong,
:ChannelList, :pointer
end

class PASSTHRU_MSG < FFI::Struct
layout :ProtocolID, :ulong,
:MsgHandle, :ulong,
:RxStatus, :ulong,
:TxFlags, :ulong,
:Timestamp, :ulong,
:DataLength, :ulong,
:ExtraDataIndex, :ulong,
:DataBuffer, :pointer,
:DataBufferSize, :ulong
end

end
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
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(2, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)
}.to raise_error Ecutools::J2534Error, /ERR_INVALID_DEVICE_ID/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

it 'returns STATUS_NOERROR when connected' do
things.test_with_ecutuned {
#PassThruConnect(deviceId, protocolId, flags, baudRate, resource, channelId)
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)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
include_context 'J2534' do
context 'PassThruOpen' do

it 'raises ERR_DEVICE_NOT_CONNECTED when no response received from PassThru device' do
it 'raises STATUS_NOERROR when successfully opened' do
things.test_with_ecutuned {
expect(j2534.PassThruOpen(things[0][:name], 1)).to eq(true)
}
Expand Down
32 changes: 0 additions & 32 deletions bindings/ruby/spec/PassThruOpen_integration_spec.rb

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,24 @@

describe Ecutools::J2534 do
include_context 'J2534' do
context 'PassThruConnect' do
context 'PassThruSelect' do

# Needs to be moved to PassThruOpen - good night!
it 'raises ERR_BUFFER_EMPTY when timeout is reached with 0 messages in the receive queue' do
things.test_with_ecutuned {

it 'returns ERR_DEVICE_IN_USE when called after already being successfully called' 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)
expect {
j2534.PassThruConnect(1, Ecutools::J2534::CAN, Ecutools::J2534::CAN_ID_BOTH, 500000, resource, 1)
}.to raise_error Ecutools::J2534Error, /ERR_DEVICE_IN_USE/
}

channelset = Ecutools::J2534::Models::ChannelSet.new
channelset.ChannelCount = 1
channelset.ChannelThreshold = 1
channelset.ChannelList = [1]

expect{j2534.PassThruSelect(channelset, 1, 1000)}.to raise_error Ecutools::J2534Error, /ERR_BUFFER_EMPTY/
}
end

end
Expand Down
6 changes: 4 additions & 2 deletions bindings/ruby/spec/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# J2534 Integration Tests

Tests that are sensitive to state have their own file due to the inability to unload a Shared Object file (libj2534.so).
Tests are in their own file so libj2534.so gets loaded fresh with each test to ensure isolation. Otherwise, all tests will share the same libj2534 state.

This way, senitive tests can be run in isolation without state from prior tests interfering.
> Running these integration tests may incur AWS fees.
rspec spec/name_of_integration_spec.rb

12 changes: 11 additions & 1 deletion bindings/ruby/spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,18 @@ def test_with_ecutuned(&block)
rescue => e
Stackit.logger.error e.message
puts e.backtrace unless e.instance_of?(Ecutools::J2534Error)
exit(1)
end
begin
`pkill -9 ecutuned`
`rm -rf /var/ecutools/cache/state_log`
rescue Errno::ENOMEM => nomem
puts "Garbage collecting to free up room for cleanup..."
GC.start
sleep(5)
`pkill -9 ecutuned`
`rm -rf /var/ecutools/cache/state_log`
end
`killall -9 ecutuned`
delete!
end

Expand Down
6 changes: 5 additions & 1 deletion cli/lib/ecutools/awsiot/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,12 @@ def save_certificates(keys_and_cert)
Dir.mkdir certs_dir unless File.exist?(certs_dir)
File.write("#{certs_dir}/#{thing_name}.crt.pem", keys_and_cert[:certificate_pem])
File.write("#{certs_dir}/#{thing_name}.key.pem", keys_and_cert[:key_pair][:private_key])
FileUtils.chmod 0600, "#{certs_dir}/#{thing_name}.key.pem"
FileUtils.cp("#{Ecutools.home}/ecutools/awsiot/ca.crt", "#{certs_dir}/ca.crt") unless File.exist?("#{certs_dir}/ca.crt")
begin
FileUtils.chmod 0600, "#{certs_dir}/#{thing_name}.key.pem"
rescue Errno::EPERM => e
puts "Failed to chmod key! Permission error."
end
end

end
Expand Down
2 changes: 1 addition & 1 deletion src/aws_iot_src/src/aws_iot_shadow.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = 7000;
mqttInitParams.mqttCommandTimeout_ms = 5000;
mqttInitParams.tlsHandshakeTimeout_ms = 10000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = pParams->disconnectHandler;
Expand Down
29 changes: 22 additions & 7 deletions src/awsiot_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ unsigned int awsiot_client_connect(awsiot_client *awsiot) {
mqttInitParams.pRootCALocation = rootCA;
mqttInitParams.pDeviceCertLocation = clientCRT;
mqttInitParams.pDevicePrivateKeyLocation = clientKey;
mqttInitParams.mqttCommandTimeout_ms = 7000;
mqttInitParams.mqttCommandTimeout_ms = 5000;
mqttInitParams.tlsHandshakeTimeout_ms = 5000;
mqttInitParams.isSSLHostnameVerify = true;
mqttInitParams.disconnectHandler = awsiot->ondisconnect;
Expand Down Expand Up @@ -87,10 +87,11 @@ bool awsiot_client_isconnected(awsiot_client *awsiot) {
return (awsiot->rc == NETWORK_RECONNECTED || awsiot->rc == SUCCESS);
}

unsigned int awsiot_client_subscribe(awsiot_client *awsiot, const char *topic, void *pApplicationHandlerData) {
syslog(LOG_DEBUG, "awsiot_client_subscribe: subscribing to topic %s.", topic);
awsiot->rc = aws_iot_mqtt_subscribe(awsiot->client, topic, strlen(topic), QOS0, awsiot->onmessage, pApplicationHandlerData);
if (SUCCESS != awsiot->rc) {
unsigned int awsiot_client_subscribe(awsiot_client *awsiot, const char *topic, void *pApplicationHandler, void *pApplicationHandlerData) {
syslog(LOG_DEBUG, "awsiot_client_subscribe: topic=%s.", topic);
void* callback = (pApplicationHandler == NULL) ? awsiot->onmessage : pApplicationHandler;
awsiot->rc = aws_iot_mqtt_subscribe(awsiot->client, topic, strlen(topic), QOS0, callback, pApplicationHandlerData);
if(SUCCESS != awsiot->rc) {
char errmsg[255];
sprintf(errmsg, "awsiot_client_subscribe: error subscribing to topic %s. IoT_Error_t: %d", topic, awsiot->rc);
if(awsiot->onerror) awsiot->onerror(awsiot, errmsg);
Expand All @@ -99,9 +100,23 @@ unsigned int awsiot_client_subscribe(awsiot_client *awsiot, const char *topic, v
return 0;
}

unsigned int awsiot_client_publish(awsiot_client *awsiot, const char *topic, const char *payload) {
unsigned int awsiot_client_unsubscribe(awsiot_client *awsiot, const char *topic) {
syslog(LOG_DEBUG, "awsiot_client_unsubscribe: topic=%s", topic);
awsiot->rc = aws_iot_mqtt_unsubscribe(awsiot->client, topic, strlen(topic));
if(SUCCESS != awsiot->rc) {
char errmsg[255];
sprintf(errmsg, "awsiot_client_unsubscribe: error unsubscribing from topic %s. IoT_Error_t: %d", topic, awsiot->rc);
if(awsiot->onerror) awsiot->onerror(awsiot, errmsg);
return 1;
}
return 0;
}

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) + 1;
syslog(LOG_DEBUG, "awsiot_client_publish: topic=%s, payload_len=%d, payload=%s", topic, payload_len, payload);

IoT_Publish_Message_Params paramsQOS0;
Expand Down
4 changes: 2 additions & 2 deletions src/awsiot_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ typedef struct _awsiot_client {

unsigned int awsiot_client_connect(awsiot_client *awsiot);
bool awsiot_client_isconnected();
unsigned int awsiot_client_subscribe(awsiot_client *awsiot, const char *topic, void *pApplicationHandlerData);
unsigned int awsiot_client_publish(awsiot_client *awsiot, const char *topic, const char *payload);
unsigned int awsiot_client_subscribe(awsiot_client *awsiot, const char *topic, void *pApplicationHandler, void *pApplicationHandlerData);
unsigned int awsiot_client_publish(awsiot_client *awsiot, const char *topic, char *payload);
void awsiot_client_close(awsiot_client *awsiot);
bool awsiot_client_build_desired_json(char *pJsonDocument, size_t maxSizeOfJsonDocument, const char *pData, uint32_t pDataLen);

Expand Down
Loading

0 comments on commit 10fdf55

Please sign in to comment.