Added batrium native protocol implementation, not working atm
This commit is contained in:
parent
ebea91d930
commit
1c7eef7089
|
@ -0,0 +1,158 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import logging
|
||||
import itertools
|
||||
|
||||
from time import time
|
||||
from datetime import datetime
|
||||
import can
|
||||
import struct
|
||||
from argparse import ArgumentParser
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
class BatriumBattery(can.Listener):
|
||||
def __init__(self, capacity, connection):
|
||||
self.capacity = capacity
|
||||
self.maxChargeVoltage = 0
|
||||
self.numberOfModules = 3
|
||||
self.chargeComplete = 0
|
||||
self.soc = 0
|
||||
self.voltage = 0
|
||||
self.current = 0
|
||||
self.temperature = 0
|
||||
self.maxCellTemperature = 0
|
||||
self.minCellTemperature = 0
|
||||
self.cellVoltages_min =[(0,0,0,0) for i in range(self.numberOfModules)]
|
||||
self.cellVoltages_max =[(0,0,0,0) for i in range(self.numberOfModules)]
|
||||
self.cellTemperatures =[(0,0,0,0) for i in range(self.numberOfModules)]
|
||||
self.cellBypassTemperatures =[(0,0,0,0) for i in range(self.numberOfModules)]
|
||||
self.cellBypassPWM =[(0,0,0,0) for i in range(self.numberOfModules)]
|
||||
self.maxCellVoltage = 0
|
||||
self.maxCellVoltageId = 0
|
||||
self.minCellVoltage = 0
|
||||
self.minCellVoltageId = 0
|
||||
self.maxChargeCurrent = 0
|
||||
self.maxDischargeCurrent = 0
|
||||
self.firmwareVersion = '2.17.39'
|
||||
self.updated = -1
|
||||
self.cyclicModeTask = None
|
||||
self.TimeToEmpty = 0
|
||||
self.TimeToFull = 0
|
||||
|
||||
self._ci = can.interface.Bus(channel=connection, bustype='socketcan')
|
||||
|
||||
# check connection and that reported system voltage roughly matches configuration
|
||||
found = False
|
||||
msg = None
|
||||
|
||||
while True:
|
||||
try:
|
||||
msg = self._ci.recv(timeout=10)
|
||||
except can.CanError:
|
||||
logging.error("Canbus error")
|
||||
|
||||
if msg == None:
|
||||
#timeout no system connected
|
||||
logging.error("No messages on canbus %s received. Check connection and speed." % connection)
|
||||
break;
|
||||
|
||||
elif msg.arbitration_id == 0x00111500:
|
||||
logging.info("Found Batrium BMS on %s" % connection)
|
||||
self.soc = (msg.data[0] * 0.5) - 5
|
||||
self.voltage = ((msg.data[3] * 256) + msg.data[2]) * 0.01
|
||||
self.current = (struct.unpack('>f', bytearray([msg.data[7], msg.data[6], msg.data[5], msg.data[4]])))[0] * 0.001
|
||||
self.temperature = msg.data[1] - 40
|
||||
|
||||
logging.debug("SOC: %2d, I: %2.2fA, U: %2.2fV, T:%2.1fC" % (self.soc, self.current, self.voltage, self.temperature))
|
||||
|
||||
found = True
|
||||
break;
|
||||
|
||||
def on_message_received(self, msg):
|
||||
self.updated = msg.timestamp
|
||||
logging.debug("CAN message arrived")
|
||||
if msg.arbitration_id == 0x00111500:
|
||||
self.soc = (msg.data[0] * 0.5) - 5
|
||||
self.voltage = ((msg.data[3] * 256) + msg.data[2]) * 0.01
|
||||
self.current = round((struct.unpack('>f', bytearray([msg.data[7], msg.data[6], msg.data[5], msg.data[4]])))[0] * 0.001, 2)
|
||||
self.temperature = msg.data[1] - 40
|
||||
|
||||
elif msg.arbitration_id == 0x00111800:
|
||||
self.TimeToEmpty = ((msg.data[2] * 256) + msg.data[1])
|
||||
|
||||
elif msg.arbitration_id == 0x00111700:
|
||||
self.TimeToFull = ((msg.data[2] * 256) + msg.data[1])
|
||||
|
||||
elif msg.arbitration_id == 0x00140400:
|
||||
self.maxDischargeCurrent = ((msg.data[3] * 256) + msg.data[2]) * 0.1
|
||||
logging.debug("Idmax %dA", self.maxDischargeCurrent)
|
||||
logging.debug("I: %dA U: %dV",self.current, self.voltage)
|
||||
|
||||
elif msg.arbitration_id == 0x00140300:
|
||||
self.maxChargeVoltage = ((msg.data[7] * 256) + msg.data[6]) * 0.01
|
||||
self.maxChargeCurrent = ((msg.data[3] * 256) + msg.data[2]) * 0.01
|
||||
logging.debug("Icmax %dA, Ivmax %dA", self.maxChargeCurrent, self.maxChargeVoltage)
|
||||
logging.debug("I: %dA U: %dV",self.current, self.voltage)
|
||||
|
||||
elif msg.arbitration_id == 0x00161700:
|
||||
self.minCellTemperature = msg.data[0] - 40
|
||||
self.maxCellTemperature = msg.data[1] - 40
|
||||
logging.debug("Min Cell Temp: %d, Max Cell Temp: %d", self.minCellTemperature, self.maxCellTemperature)
|
||||
|
||||
elif msg.arbitration_id == 0x00161100:
|
||||
self.minCellVoltage = ((msg.data[1] * 256) + msg.data[0]) * 0.001
|
||||
self.maxCellVoltage = ((msg.data[3] * 256) + msg.data[2]) * 0.001
|
||||
self.minCellVoltageId = msg.data[4]
|
||||
self.maxCellVoltageId = msg.data[5]
|
||||
logging.debug("Umin %1.3fV Umax %1.3fV", self.minCellVoltage, self.maxCellVoltage)
|
||||
|
||||
elif ((msg.arbitration_id >= 0x001D1101) and (msg.arbitration_id <= 0x001D11F9)):
|
||||
cell_id = msg.arbitration_id & 0xff
|
||||
logging.debug("Cell ID: %d", cell_id)
|
||||
#self.cellVoltages_min[cell_id] = ((msg.data[1] * 256) + msg.data[0]) * 0.001
|
||||
#self.cellVoltages_max[cell_id] = ((msg.data[3] * 256) + msg.data[2]) * 0.001
|
||||
#self.cellTemperatures[cell_id] = msg.data[4] - 40
|
||||
#self.cellBypassTemperatures[cell_id] = msg.data[5] - 40
|
||||
#self.cellBypassPWM[cell_id] = msg.data[6]
|
||||
|
||||
def prnt(self):
|
||||
print("SOC: %2d, I: %2.2fA, U: %2.2fV, T:%2.1fC" % (self.soc, self.current, self.voltage, self.maxCellTemperature))
|
||||
print("Umin: %1.2f, Umax: %1.2f Udelta: %1.2f" % (self.minCellVoltage, self.maxCellVoltage, self.maxCellVoltage-self.minCellVoltage))
|
||||
print("CCL: %4.1f A CVL: %2.2f V" % (self.maxChargeCurrent, self.maxChargeVoltage))
|
||||
|
||||
# === All code below is to simply run it from the commandline for debugging purposes ===
|
||||
def main():
|
||||
|
||||
logging.info('Starting dbus_batrium_native listener')
|
||||
|
||||
#logger = can.Logger('logfile.asc')
|
||||
|
||||
bat = BatriumBattery(capacity=300, connection='can0')
|
||||
|
||||
listeners = [
|
||||
#logger, # Regular Listener object
|
||||
bat
|
||||
]
|
||||
|
||||
notifier = can.Notifier(bat._ci, listeners)
|
||||
for msg in bat._ci:
|
||||
if msg.arbitration_id == 0x00140100:
|
||||
bat.prnt()
|
||||
|
||||
# Clean-up
|
||||
notifier.stop()
|
||||
bat._ci.shutdown()
|
||||
|
||||
|
||||
logging.basicConfig( format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S',
|
||||
level=(logging.DEBUG),
|
||||
handlers=[
|
||||
logging.FileHandler("%s/current.log" % (os.path.dirname(os.path.realpath(__file__)))),
|
||||
logging.StreamHandler()
|
||||
])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,274 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
A class to put a battery service on the dbus, according to victron standards, with constantly updating
|
||||
paths.
|
||||
|
||||
"""
|
||||
from gi.repository import GLib
|
||||
import platform
|
||||
import argparse
|
||||
import logging
|
||||
import sys
|
||||
import os
|
||||
import dbus
|
||||
import itertools
|
||||
import math
|
||||
|
||||
from time import time
|
||||
from datetime import datetime
|
||||
import struct
|
||||
from argparse import ArgumentParser
|
||||
|
||||
from batrium import *
|
||||
|
||||
|
||||
# our own packages
|
||||
sys.path.insert(1, os.path.join(os.path.dirname(__file__), '/opt/victronenergy/dbus-systemcalc-py/ext/velib_python'))
|
||||
from vedbus import VeDbusService
|
||||
from ve_utils import exit_on_error
|
||||
from settingsdevice import SettingsDevice
|
||||
|
||||
VERSION = '1.0'
|
||||
|
||||
def handle_changed_setting(setting, oldvalue, newvalue):
|
||||
logging.debug('setting changed, setting: %s, old: %s, new: %s' % (setting, oldvalue, newvalue))
|
||||
|
||||
|
||||
class DbusBatteryService:
|
||||
def __init__(self, servicename, deviceinstance, capacity, productname='Batrium BMS', connection='can0'):
|
||||
self.minUpdateDone = 0
|
||||
self.dailyResetDone = 0
|
||||
self.lastUpdated = 0
|
||||
self._bat = BatriumBattery(capacity=capacity, connection=connection)
|
||||
|
||||
try:
|
||||
self._dbusservice = VeDbusService(servicename+'.socketcan_'+connection+'_di'+str(deviceinstance))
|
||||
except:
|
||||
exit
|
||||
|
||||
# Create the management objects, as specified in the ccgx dbus-api document
|
||||
self._dbusservice.add_path('/Mgmt/ProcessName', __file__)
|
||||
self._dbusservice.add_path('/Mgmt/ProcessVersion', VERSION + ' running on Python ' + platform.python_version())
|
||||
self._dbusservice.add_path('/Mgmt/Connection', connection)
|
||||
|
||||
# Create the mandatory objects
|
||||
self._dbusservice.add_path('/DeviceInstance', deviceinstance)
|
||||
self._dbusservice.add_path('/ProductId', 0)
|
||||
self._dbusservice.add_path('/ProductName', productname)
|
||||
self._dbusservice.add_path('/FirmwareVersion', 'unknown')
|
||||
self._dbusservice.add_path('/HardwareVersion', 'unknown')
|
||||
self._dbusservice.add_path('/Connected', 0)
|
||||
# Create battery specific objects
|
||||
self._dbusservice.add_path('/Status', 0)
|
||||
self._dbusservice.add_path('/Soh', 100)
|
||||
self._dbusservice.add_path('/Capacity', int(capacity))
|
||||
self._dbusservice.add_path('/InstalledCapacity', int(capacity))
|
||||
self._dbusservice.add_path('/Dc/0/Temperature', 20)
|
||||
self._dbusservice.add_path('/Info/MaxChargeCurrent', 5)
|
||||
self._dbusservice.add_path('/Info/MaxDischargeCurrent', 5)
|
||||
self._dbusservice.add_path('/Info/MaxChargeVoltage', 0)
|
||||
self._dbusservice.add_path('/Info/BatteryLowVoltage', 48.0)
|
||||
self._dbusservice.add_path('/Alarms/CellImbalance', 0)
|
||||
self._dbusservice.add_path('/Alarms/LowVoltage', 0)
|
||||
self._dbusservice.add_path('/Alarms/HighVoltage', 0)
|
||||
self._dbusservice.add_path('/Alarms/HighDischargeCurrent', 0)
|
||||
self._dbusservice.add_path('/Alarms/HighChargeCurrent', 0)
|
||||
self._dbusservice.add_path('/Alarms/LowSoc', 0)
|
||||
self._dbusservice.add_path('/Alarms/LowTemperature', 0)
|
||||
self._dbusservice.add_path('/Alarms/HighTemperature', 0)
|
||||
self._dbusservice.add_path('/Balancing', 0)
|
||||
self._dbusservice.add_path('/System/HasTemperature', 1)
|
||||
self._dbusservice.add_path('/System/NrOfBatteries', 1)
|
||||
self._dbusservice.add_path('/System/NrOfModulesOnline', 1)
|
||||
self._dbusservice.add_path('/System/NrOfModulesOffline', 0)
|
||||
self._dbusservice.add_path('/System/NrOfModulesBlockingDischarge', 0)
|
||||
self._dbusservice.add_path('/System/NrOfModulesBlockingCharge', 0)
|
||||
self._dbusservice.add_path('/System/NrOfBatteriesBalancing', 0)
|
||||
self._dbusservice.add_path('/System/BatteriesParallel', 1)
|
||||
self._dbusservice.add_path('/System/BatteriesSeries', 1)
|
||||
self._dbusservice.add_path('/System/NrOfCellsPerBattery', 4)
|
||||
self._dbusservice.add_path('/System/MinVoltageCellId', 0)
|
||||
self._dbusservice.add_path('/System/MaxVoltageCellId', 0)
|
||||
self._dbusservice.add_path('/System/MinCellTemperature', 10.0)
|
||||
self._dbusservice.add_path('/System/MaxCellTemperature', 10.0)
|
||||
|
||||
self._settings = SettingsDevice(
|
||||
bus=dbus.SystemBus() if (platform.machine() == 'armv7l') else dbus.SessionBus(),
|
||||
supportedSettings={
|
||||
'AvgDischarge': ['/Settings/Batrium/AvgerageDischarge', 0.0,0,0],
|
||||
'TotalAhDrawn': ['/Settings/Batrium/TotalAhDrawn', 0.0,0,0],
|
||||
'TimeLastFull': ['/Settings/Batrium/TimeLastFull', 0.0 ,0,0],
|
||||
'MinCellVoltage': ['/Settings/Batrium/MinCellVoltage', 4.0,2.0,4.2],
|
||||
'MaxCellVoltage': ['/Settings/Batrium/MaxCellVoltage', 2.0,2.0,4.2],
|
||||
'interval': ['/Settings/Batrium/Interval', 10, 10, 10]
|
||||
},
|
||||
eventCallback=handle_changed_setting)
|
||||
|
||||
|
||||
self._summeditems = {
|
||||
'/System/MaxCellVoltage': {'gettext': '%.2F V'},
|
||||
'/System/MinCellVoltage': {'gettext': '%.2F V'},
|
||||
'/Dc/0/Voltage': {'gettext': '%.2F V'},
|
||||
'/Dc/0/Current': {'gettext': '%.1F A'},
|
||||
'/Dc/0/Power': {'gettext': '%.0F W'},
|
||||
'/Soc': {'gettext': '%.0F %%'},
|
||||
'/History/TotalAhDrawn': {'gettext': '%.0F Ah'},
|
||||
'/History/DischargedEnergy': {'gettext': '%.2F kWh'},
|
||||
'/History/ChargedEnergy': {'gettext': '%.2F kWh'},
|
||||
'/History/AverageDischarge': {'gettext': '%.2F kWh'},
|
||||
'/TimeToGo': {'gettext': '%.0F s'},
|
||||
'/ConsumedAmphours': {'gettext': '%.1F Ah'}
|
||||
}
|
||||
|
||||
for path in self._summeditems.keys():
|
||||
self._dbusservice.add_path(path, value=None, gettextcallback=self._gettext)
|
||||
|
||||
self._dbusservice['/History/AverageDischarge'] = self._settings['AvgDischarge']
|
||||
self._dbusservice['/History/TotalAhDrawn'] = self._settings['TotalAhDrawn']
|
||||
self._dbusservice.add_path('/History/TimeSinceLastFullCharge', 0)
|
||||
self._dbusservice.add_path('/History/MinCellVoltage', self._settings['MinCellVoltage'])
|
||||
self._dbusservice.add_path('/History/MaxCellVoltage', self._settings['MaxCellVoltage'])
|
||||
self._dbusservice['/ConsumedAmphours'] = 0
|
||||
|
||||
logging.info("History cell voltage min: %.3f, max: %.3f, totalAhDrawn: %d",
|
||||
self._settings['MinCellVoltage'], self._settings['MaxCellVoltage'], self._settings['TotalAhDrawn'])
|
||||
|
||||
self._dbusservice['/History/ChargedEnergy'] = 0
|
||||
self._dbusservice['/History/DischargedEnergy'] = 0
|
||||
|
||||
GLib.timeout_add( self._settings['interval'], exit_on_error, self._update)
|
||||
|
||||
def _gettext(self, path, value):
|
||||
item = self._summeditems.get(path)
|
||||
if item is not None:
|
||||
return item['gettext'] % value
|
||||
return str(value)
|
||||
|
||||
def __del__(self):
|
||||
self._safe_history()
|
||||
logging.info('Stopping dbus_Batrium')
|
||||
|
||||
|
||||
def _safe_history(self):
|
||||
logging.debug('Saving history to localsettings')
|
||||
self._settings['AvgDischarge'] = self._dbusservice['/History/AverageDischarge']
|
||||
self._settings['TotalAhDrawn'] = self._dbusservice['/History/TotalAhDrawn']
|
||||
self._settings['MinCellVoltage'] = self._dbusservice['/History/MinCellVoltage']
|
||||
self._settings['MaxCellVoltage'] = self._dbusservice['/History/MaxCellVoltage']
|
||||
|
||||
|
||||
def _daily_stats(self):
|
||||
if (self._dbusservice['/History/DischargedEnergy'] == 0): return
|
||||
logging.info("Updating stats, SOC: %d, Discharged: %.2f, Charged: %.2f ",self._bat.soc, self._dbusservice['/History/DischargedEnergy'], self._dbusservice['/History/ChargedEnergy'])
|
||||
self._dbusservice['/History/AverageDischarge'] = (6*self._dbusservice['/History/AverageDischarge'] + self._dbusservice['/History/DischargedEnergy'])/7 #rolling week
|
||||
self._dbusservice['/History/ChargedEnergy'] = 0
|
||||
self._dbusservice['/History/DischargedEnergy'] = 0
|
||||
dt = datetime.now() - datetime.fromtimestamp( float(self._settings['TimeLastFull']) )
|
||||
|
||||
#if full within the last 24h and more than *0% consumed, estimate actual capacity and SOH based on consumed amphours from full and SOC reported
|
||||
if dt.total_seconds() < 24*3600 and self._bat.soc < 70:
|
||||
self._dbusservice['/Capacity'] = int(-self._dbusservice['/ConsumedAmphours'] * 100 / (100-self._bat.soc))
|
||||
self._dbusservice['/Soh'] = int(self._dbusservice['/Capacity']*100 / self._dbusservice['/InstalledCapacity'])
|
||||
logging.info("SOH: %d, Capacity: %d ", self._dbusservice['/Soh'], self._dbusservice['/Capacity'])
|
||||
self.dailyResetDone = datetime.now().day
|
||||
|
||||
|
||||
def _update(self):
|
||||
if (self._bat.updated != -1 and self.lastUpdated == 0) or ((self._bat.updated - self.lastUpdated) < 1000):
|
||||
self.lastUpdated = self._bat.updated
|
||||
self._dbusservice['/Connected'] = 1
|
||||
else:
|
||||
self._dbusservice['/Connected'] = 0
|
||||
|
||||
self._dbusservice['/Dc/0/Current'] = self._bat.current
|
||||
self._dbusservice['/Dc/0/Voltage'] = self._bat.voltage
|
||||
power = self._bat.voltage * self._bat.current
|
||||
self._dbusservice['/Dc/0/Power'] = power
|
||||
self._dbusservice['/Dc/0/Temperature'] = self._bat.maxCellTemperature
|
||||
|
||||
self._dbusservice['/System/MaxVoltageCellId'] = self._bat.maxCellVoltageId
|
||||
self._dbusservice['/System/MinVoltageCellId'] = self._bat.minCellVoltageId
|
||||
self._dbusservice['/System/MaxCellVoltage'] = self._bat.maxCellVoltage
|
||||
if (self._bat.maxCellVoltage > self._dbusservice['/History/MaxCellVoltage'] ):
|
||||
self._dbusservice['/History/MaxCellVoltage'] = self._bat.maxCellVoltage
|
||||
logging.info("New maximum cell voltage: %f", self._bat.maxCellVoltage)
|
||||
self._dbusservice['/System/MinCellVoltage'] = self._bat.minCellVoltage
|
||||
if (0 < self._bat.minCellVoltage < self._dbusservice['/History/MinCellVoltage'] ):
|
||||
self._dbusservice['/History/MinCellVoltage'] = self._bat.minCellVoltage
|
||||
logging.info("New minimum cell voltage: %f", self._bat.minCellVoltage)
|
||||
self._dbusservice['/System/MinCellTemperature'] = self._bat.minCellTemperature
|
||||
self._dbusservice['/System/MaxCellTemperature'] = self._bat.maxCellTemperature
|
||||
self._dbusservice['/Info/MaxChargeCurrent'] = self._bat.maxChargeCurrent
|
||||
self._dbusservice['/Info/MaxDischargeCurrent'] = self._bat.maxDischargeCurrent
|
||||
self._dbusservice['/Info/MaxChargeVoltage'] = self._bat.maxChargeVoltage
|
||||
self._dbusservice['/System/NrOfModulesOnline'] = self._bat.numberOfModules
|
||||
|
||||
#update energy statistics daily at 6:00,
|
||||
if datetime.now().hour == 6 and datetime.now().minute == 0 and datetime.now().day != self.dailyResetDone :
|
||||
self._daily_stats()
|
||||
|
||||
now = datetime.now().time()
|
||||
if now.minute != self.minUpdateDone:
|
||||
self.minUpdateDone = now.minute
|
||||
if self._bat.current > 0:
|
||||
#charging
|
||||
self._dbusservice['/TimeToGo'] = self._bat.TimeToFull
|
||||
else :
|
||||
#discharging
|
||||
self._dbusservice['/TimeToGo'] = self._bat.TimeToEmpty
|
||||
|
||||
self._safe_history()
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
parser = ArgumentParser(description='dbus_batrium', add_help=True)
|
||||
parser.add_argument('-d', '--debug', help='enable debug logging',
|
||||
action='store_true')
|
||||
parser.add_argument('-i', '--interface', help='CAN interface')
|
||||
parser.add_argument('-c', '--capacity', help='capacity in Ah')
|
||||
parser.add_argument('-p', '--print', help='print only')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
logging.basicConfig( format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S',
|
||||
level=(logging.DEBUG if args.debug else logging.INFO),
|
||||
handlers=[
|
||||
logging.FileHandler("%s/current.log" % (os.path.dirname(os.path.realpath(__file__)))),
|
||||
logging.StreamHandler()
|
||||
])
|
||||
|
||||
if not args.interface:
|
||||
logging.info('No CAN interface specified, using default can0')
|
||||
args.interface = 'can0'
|
||||
|
||||
if not args.capacity:
|
||||
logging.warning('Battery capacity not specified, using default (100Ah)')
|
||||
args.capacity = 100
|
||||
|
||||
logging.info('Starting dbus_batrium %s on %s ' %
|
||||
(VERSION, args.interface))
|
||||
|
||||
logging.debug('Setup main loop')
|
||||
|
||||
from dbus.mainloop.glib import DBusGMainLoop
|
||||
# Have a mainloop, so we can send/receive asynchronous calls to and from dbus
|
||||
DBusGMainLoop(set_as_default=True)
|
||||
|
||||
logging.debug('Setup dbus service')
|
||||
|
||||
battery_output = DbusBatteryService(
|
||||
servicename='com.victronenergy.battery',
|
||||
connection = args.interface,
|
||||
deviceinstance = 0,
|
||||
capacity = int(args.capacity),
|
||||
)
|
||||
|
||||
logging.debug('Connected to dbus, and switching over to GLib.MainLoop() (= event based)')
|
||||
mainloop = GLib.MainLoop()
|
||||
mainloop.run()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,3 @@
|
|||
opkg update
|
||||
opkg install python3-pip
|
||||
pip3 install python-can
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
exec 2>&1
|
||||
exec softlimit -d 100000000 -s 1000000 -a 100000000 python /data/dbus_batrium_native/dbus_batrium_native.py -i can0 -c 300
|
Loading…
Reference in New Issue