Skip to content
This repository was archived by the owner on Jun 28, 2023. It is now read-only.

Request/Response + ISO-TP #1

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 81 additions & 35 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,47 +27,93 @@ deactivate
```

## Usage:
At the moment you have to use the python shell. I script for nicer commands is on the way.

### listen to a single packet
``` python
from thingset.cansocket import CANsocket
sock = CANsocket('vcan0') # or other interface
frame = sock.receive()
print(frame.data) # raw data
print(frame.cbor) # cbor decoded data
print(frame.priority)
print(frame.dataobjectID)
print(frame.source)

### Initialization

```python
from thingset.thingset_can import ThingSet_CAN

# Define some addresses
own_id = 0x01
bms_id = 0x0A
mppt_id = 0x14

# Create ThingSet client object with CAN interface and source ID
ts = ThingSet_CAN(if_name='can0', own_id=own_id)
# Subscribe to publication messages of specific devices
ts.subscribe(bms_id)
ts.subscribe(mppt_id)
# Start reception process
rx_thread.start()
```

### listen to packets in a loop:
``` python
from thingset.cansocket import CANsocket
sock = CANsocket('vcan0') # or other interface
while(True)
frame = sock.receive()
### Callback Mechanism

It is possible to register a callback function that is called on every received publication frame to process the frame directly after reception.

```python
def pub_callback(src:int, id:int, data):
'''Callback function for received Publication Frames'''
print(f'Message from ID {src} -> {id}: {data}')

ts.setPubCallback(pub_callback)
```

### Request API

* Return data is dependent on request type
* can be:
* status code (string)
* bool
* int
* float
* string
* array (Python List)
* map (Python Dictionary)

#### get

```python
# Retrieve all data from a path
meas_id = ts.get(bms_id, 0x02)))
meas_str = ts.get(bms_id, 'meas')))

# Retrieve single data items
deviceID = ts.get(bms_id, 0x1D)))
can_enable = ts.get(bms_id, 0xF6)))
bat_V = ts.get(bms_id, 0x71)))

# Retrieve array data items
cell_V = ts.get(bms_id, 0x80)))
```

### parse can trace
Assuming the trace file ist called "trace123.csv":
``` python
from thingset.parser import playback
playback('trace123.csv")
#### fetch

```python
# fetch BatNom_Ah from CONF Path
batNom_Ah = ts.fetch(bms_id, 0x06, [0x31])

# fetch multiple items with an array
response = ts.fetch(bms_id, 0x06, [0x31, 0x41])
```

## send dummy data via cansend to test:
``` shell
cansend vcan0 014#8000FA3FF33333
cansend vcan0 014#8000820C16
cansend vcan0 014#8000C48221196AB3
cansend vcan0 014#8080C48221196AB3
#### post

```python
# call print-registers function
response = ts.post(bms_id, 0xEC, [])

# call print-register function with argument
response = ts.post(bms_id, 0xEA, [0x4B])))

# Athenticate
response = ts.post(bms_id, 0xEE, ["maker456"])
response = ts.post(bms_id, 0xEE, ["expert123"])
```

The output should look like this:
``` shell
Message from ID 20 -> 0: 1.899999976158142
Message from ID 20 -> 0: [12, 22]
Message from ID 20 -> 0: 273.15
Error receiving package from ID 20. Error code: 0x80
#### patch

```python
# iPatch (bool) - can.enable = False
response = ts.patch(bms_id, 0xF5, {0xF6: False})
```
105 changes: 97 additions & 8 deletions test.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,99 @@
# Tested with BMS-8S50-IC
# HW v0.1.1
# FW v21.0-57-g6c0fb5f-dirty

from thingset.cansocket import CANsocket
sock = CANsocket('can0') # or other interface
import threading
import time
from thingset.thingset_can import ThingSet_CAN

while(True):
frame = sock.receive()
if isinstance(frame.cbor, float):
print("device: 0x%x data id: 0x%x value: %.2f" % (frame.source, frame.dataobjectID, frame.cbor))
else:
print("device:", hex(frame.source), " data id:", hex(frame.dataobjectID), " value:", frame.cbor)
own_id = 0x01
bms_id = 0x0A
mppt_id = 0x14


def pub_callback(src: int, id: int, data):
'''Callback function for received Publication Frames'''
print(f'Message from ID {src} -> {id}: {data}')


ts = ThingSet_CAN(if_name='can0', own_id=own_id)
ts.subscribe(bms_id)
ts.subscribe(mppt_id)
ts.setPubCallback(pub_callback)
ts.start()

print("Python ThingSet Client for CAN (Binary Mode)")
print("--------------------------------------------")

# WORKING =====================================================

# GET
print(" > Get - INFO Path: " + str(ts.get(bms_id, 0x01)))
print(" > Get - INFO Path: " + str(ts.get(bms_id, 'info')))
print(" > Get - MEAS Path: " + str(ts.get(bms_id, 0x02)))
print(" > Get - MEAS Path: " + str(ts.get(bms_id, 'meas')))
print(" > Get - INPUT Path: " + str(ts.get(bms_id, 0x05)))
print(" > Get - CONF Path: " + str(ts.get(bms_id, 0x06)))
print(" > Get - can.Enable: " + str(ts.get(bms_id, 0xF6)))
print(" > Get - meas.Bat_V: " + str(ts.get(bms_id, 0x71)))
print(" > Get - meas.Cell_V: " + str(ts.get(bms_id, 0x80)))
print(" > Get - DeviceID: " + str(ts.get(bms_id, 0x1D)))

# PATCH
print(" > iPatch (bool) - Discharge disable: " + str(ts.patch(bms_id, 0x05, {0x61: False})))
print(" > iPatch (bool) - Discharge enable: " + str(ts.patch(bms_id, 0x05, {0x61: True})))
print(" > iPatch (string) - Password = abcd: " + str(ts.patch(bms_id, 0xEE, {0xEF: 'abcd'})))
print(" iPatch (int) - PcbDisSC_us = 200: " + str(ts.patch(bms_id, 0x06, {0x41: 200})))
print(" iPatch (bool) - .pub.can.enable = False: " + str(ts.patch(bms_id, 0xF5, {0xF6: False})))
print(" iPatch (bool) - .pub.can.enable = True: " + str(ts.patch(bms_id, 0xF5, {0xF6: True})))

# FETCH
print(" > Fetch - Request BatNom_Ah from CONF Path: " + str(ts.fetch(bms_id, 0x06, [0x31])))
print(" > Fetch - Request Array: " + str(ts.fetch(bms_id, 0x06, [0x31, 0x41])))

# POST - Execute Function
print(" > Post - print-registers: " + str(ts.post(bms_id, 0xEC, [])))
print(" > Post - print-register: " + str(ts.post(bms_id, 0xEA, [0x4B])))
print(" > Post - auth: " + str(ts.post(bms_id, 0xEE, ["maker456"])))
print(" > Post - auth: " + str(ts.post(bms_id, 0xEE, ["expert123"])))

# ISSUES =======================================================

# print(" > Fetch - MEAS item IDs: " + str(ts.fetch(bms_id, 0x02, 0xF7)))
# Returs: Error - Response too large (0xE1)

# print(" > Post - Append : " + str(ts.post(bms_id, 0x100, 0x74)))

# print(" > Get - .pub Path: " + str(ts.get(bms_id, 0x100)))
# returns: 1EDA010A 06 85 A2 18 F1 18 F5
# cbor2.loads(b'\xa2\x18\xf1\x18\xf5') -> premature end of stream (expected to read 1 bytes, got 0 instead)

# print(" > Get - serial: " + str(ts.get(bms_id, 0xF3)))
# Returns: 1EDA010A 01 85
# print(" > Get - can: " + str(ts.get(bms_id, 0xF7)))
# Returns: 1EDA010A 01 85

# print(" > Get - serial: " + str(ts.get(bms_id, 0xF1)))
# Returns: 1EDA010A 07 85 A2 18 F3 18 F2 F4
# cbor2.loads(b'\xa2\x18\xf3\x18\xf2\xf4') -> premature end of stream (expected to read 1 bytes, got 0 instead)
# print(" > Get - can: " + str(ts.get(bms_id, 0xF5)))
# Returns: 1EDA010A 07 85 A2 18 F7 18 F6 F5
# cbor2.loads(b'\xa2\x18\xf7\x18\xf6\xf5') -> premature end of stream (expected to read 1 bytes, got 0 instead)

# Fetch Names returns values not strings (diff from spec)
# print(" > Fetch - Names: " + str(ts.fetch(bms_id, 0x17, [0x40, 0x41])))
# returns: 1EDA010A 10 09 85 82 FA 00 00 00
# 1EDA010A 21 BE 18 C8

# ==============================================================

print("Exit with Ctrl+C ")

try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print('interrupted!')

print("Latest BMS Pub. Data: " + str(ts.data[bms_id]))
print("Latest MPPT Pub. Data: " + str(ts.data[mppt_id]))
Loading