327 lines
17 KiB
Python
327 lines
17 KiB
Python
#!/usr/bin/python3
|
|
|
|
####
|
|
# This is a sample program, which introduces the functions and applications of the Baby-LIN-DLL. To run this program you need the current LINWorks software and
|
|
# a Baby-LIN device from Lipowsky Industrie-Elektronik GmbH. Make sure that there is a USB connection between your PC and the Baby-LIN-Device and
|
|
# that a voltage of 8-26 VDC is applied to the LIN-Bus.
|
|
#
|
|
# Table of Contents:
|
|
# 1. Display Version of Baby-LIN-DLL und Wrapper
|
|
# 2. Connection with the Baby-LIN-Device
|
|
# 3. Connection to the LIN-Channel
|
|
# 4. Write SerialNumber to signal
|
|
# 5. Excecute macro and processing MacroResultString
|
|
# 6. Use of getsig/setsig for signal handling
|
|
# 7. Frame registration and display of the framecallbacks
|
|
# 8. Error handling
|
|
####
|
|
|
|
from __future__ import unicode_literals
|
|
from asyncio.windows_events import NULL
|
|
from ctypes import *
|
|
from hashlib import new
|
|
import os, sys, argparse, six
|
|
|
|
try:
|
|
# import the BabyLIN Python wrapper
|
|
import BabyLIN_library
|
|
except ImportError as e:
|
|
six.print_(e)
|
|
|
|
def parse_arguments():
|
|
""" """
|
|
# get sdf file from the path where the executable is
|
|
parser = argparse.ArgumentParser(description="run `main.py` on sdf file")
|
|
parser.add_argument("-s", "--sdf", help="sdf file to load",
|
|
default="Example.sdf")
|
|
parser.add_argument("-v", "--verbose", action="count", default=0)
|
|
args = parser.parse_args()
|
|
|
|
return args.sdf, args.verbose
|
|
|
|
def main(sdf_name, verbose):
|
|
""" Standard example. """
|
|
|
|
def framecallback(handle, frame):
|
|
""" frame callback to be used later."""
|
|
six.print_(frame)
|
|
return 0
|
|
|
|
if verbose == 1:
|
|
six.print_("Using dynamic library " + BabyLIN.BABYLIN_DLL_PATH_NAME)
|
|
|
|
# create the BabyLIN class contained in BabyLIN_DLL.py
|
|
BabyLIN = BabyLIN_library.create_BabyLIN()
|
|
|
|
# inject BabyLIN names into local namespace, so you can, e.g. write
|
|
# BLC_getVersion instead of BabyLIN.BLC_getVersion
|
|
for k, v in BabyLIN.__dict__['_libNames'].items():
|
|
globals()[k] = getattr(BabyLIN, k)
|
|
|
|
if verbose == 1:
|
|
six.print_("Using sdf file " + sdf_name)
|
|
|
|
try:
|
|
six.print_("Test programm started")
|
|
six.print_("#####################################")
|
|
six.print_("")
|
|
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 1. Display Version of Baby-LIN-DLL und Wrapper
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# Display the version of the BabyLIN DLL and the .net Wrapper
|
|
six.print_("DLL and wrapper version are read out")
|
|
six.print_("")
|
|
dllVersion = BLC_getVersionString()
|
|
wrapperVersion = BLC_getWrapperVersion()
|
|
six.print_("BabyLIN version: ", dllVersion)
|
|
six.print_("BabyLIN python Wrapper version: ", wrapperVersion)
|
|
six.print_("")
|
|
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 2. Connection with the Baby-LIN-Device
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# Search for Baby-LIN devices
|
|
# The BLC_getBabyLinPortsTimeout() function is also searching for network devices
|
|
# If you are using only Baby-LIN devices with USB port, you can use BLC_getBabyLinPorts()
|
|
portCount = 100 # Find up to 100 devices
|
|
six.print_("Search for Baby-LIN-Devices for connection...")
|
|
portList = BLC_getBabyLinPorts(portCount)
|
|
if portList == 0:
|
|
six.print_("Could not find any Baby-LIN devices.")
|
|
sys.exit(-1)
|
|
|
|
six.print_(str(len(portList)) + " devices were found for the connection")
|
|
six.print_("")
|
|
|
|
portList = BLC_getBabyLinPortsTimout(portCount, 3000)
|
|
if portList == 0:
|
|
six.print_("Could not find any Baby-LIN devices.")
|
|
sys.exit(-1)
|
|
|
|
# In this example, we will be using the first found Baby-LIN device
|
|
if len(portList) < 1:
|
|
six.print_("Could not find any Baby-LIN devices.")
|
|
sys.exit(-1)
|
|
port = portList[0]
|
|
|
|
# Open a connection to the first found BabyLIN
|
|
six.print_("The connection to the first Baby-LIN-Device of the portlist is established.")
|
|
handle = BLC_openPort(port)
|
|
if handle == NULL:
|
|
six.print_("The connection to the BabyLIN could not be opened. Please check, that the COM Port is correct.")
|
|
sys.exit(-1)
|
|
|
|
# Download the SDF file into the BabyLIN device
|
|
six.print_("SDF download...")
|
|
six.print_("")
|
|
rc = BLC_loadSDF(handle, sdf_name, 1)
|
|
if rc != 0:
|
|
six.print_("The SDF file could not be loaded into the BabyLIN. Please check, that the filename is correct.")
|
|
sys.exit(-1)
|
|
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 3. Connection to the LIN-Channel
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# Get the number of available channels
|
|
six.print_("Output of the channel info")
|
|
channelCount = BLC_getChannelCount(handle)
|
|
six.print_("available channels: " + str(channelCount))
|
|
|
|
# the example will open the first device with an included
|
|
# LIN channel, download the sdf to it, start the LIN bus,
|
|
# register a frame-callback and watch the incoming LIN-frames
|
|
# in the callback.
|
|
|
|
# open the device(s)
|
|
conHandle = (handle for port in portList)
|
|
|
|
# get the device's number of channels
|
|
channelCount = ((BLC_getChannelCount(h), h) for h in conHandle)
|
|
|
|
# among these, look for the first LIN channel:
|
|
channelRange = ((range(chNr), h) for chNr, h in channelCount)
|
|
|
|
# first, get the corresponding channel handles
|
|
channelHandle = ((BLC_getChannelHandle(h, channelIndex), h)
|
|
for r, h in channelRange for channelIndex in r)
|
|
|
|
# for each channel (handle), get the channel info
|
|
chInfo = ((BLC_getChannelInfo(ch), h, ch) for ch, h in channelHandle)
|
|
|
|
# using the channel info, filter the LIN channels
|
|
# using 'info.type == 0'
|
|
conH_chH = ((h, ch) for info, h, ch in chInfo if info.type == 0)
|
|
|
|
for conHandle, channelHandle in conH_chH:
|
|
|
|
# for debugging, print ChannelInfo
|
|
channelInfos = BLC_getChannelInfo(channelHandle)
|
|
six.print_("Channel info: Name=" + str(channelInfos.name) + " , Type=" + str(channelInfos.type) + " , MaxBaudrate=" + str(channelInfos.maxbaudrate))
|
|
|
|
# start the LIN bus
|
|
six.print_("Connect to channel number 1 and start the schedule number 0")
|
|
six.print_("")
|
|
scheduleNr = 0
|
|
rc = BLC_sendCommand(channelHandle, "start schedule " + str(scheduleNr) + ";")
|
|
if rc != 0:
|
|
six.print_("Could not start the LIN bus.")
|
|
sys.exit(-1)
|
|
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 4. Write SerialNumber to signal
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# Write Signal Serial_Number
|
|
# The SDF provides the following signals: SN_Byte_0, SN_Byte_1, SN_Byte_2 ,SN_Byte_3, SN_Byte_4, SN_Byte_5, SN_Byte_6, SN_Byte_7
|
|
# With the BLCvarWrite() command the signals can all be written with one operation. The varible data_len determines the number of signals to be set.
|
|
# Exactly one byte is assigned to each signal
|
|
six.print_("Precessing the serial number")
|
|
signal_nr = 0
|
|
data_len = 8
|
|
data = bytes([83, 78, 48, 49, 50, 51, 52, 53]) # ASCII-Code: "SN012345"
|
|
rc = BLC_varWrite(channelHandle, signal_nr, data, data_len)
|
|
if rc != 0:
|
|
six.print_("Could not write into signal Serial_Number.")
|
|
sys.exit(-1)
|
|
|
|
# Read signal Serial_number for control
|
|
# The BLC_varRead() command reads a certain number of signals and stores them in a byte buffer, which is passed to the function when it is called.
|
|
# The number of signals to be read is determined by the variable lenght.
|
|
lenght = 8
|
|
SignalValue = BLC_varRead(channelHandle, signal_nr, lenght)
|
|
if SignalValue == 0:
|
|
six.print_("Could not read the signal Serial_Number.")
|
|
sys.exit(-1)
|
|
six.print_("Serial number set via BLC_varWrite command")
|
|
six.print_("")
|
|
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 5. Excecute macro and processing MacroResultString
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# Execute 01_process_SerialNumber
|
|
# In this macro the data from the SN_Byte signals are read out and combined to a result string.
|
|
# The Baby_LIN_DLL provides a set of Baby_LIN commands which can be executed with the BLC_sendCommand().
|
|
#
|
|
# The macro_exec command executes the macro with the passed macro number. The BLC command does not wait until the macro is fully executed.
|
|
# This must be implemented by the user with the function BLC_macro_result. As long as the macro is still executed, the BLC function returns the value 150.
|
|
six.print_("Create MacroResultString out of serial number bytes")
|
|
macro_nr = 0
|
|
return_value = 0
|
|
timeout_ms = 250
|
|
rc = BLC_sendCommand(channelHandle, "macro_exec " + str(macro_nr) + ";")
|
|
if rc != 0:
|
|
six.print_("BLC command could not be executed.")
|
|
sys.exit(-1)
|
|
rc = BLC_macro_result(channelHandle, macro_nr, timeout_ms)
|
|
if rc != 0:
|
|
six.print_("BLC command could not be executed.")
|
|
sys.exit(-1)
|
|
|
|
# Get MacroResultString
|
|
# When executing a macro it returns a result string after successful completion.This can be set additionally by MAcro command print.
|
|
# With parameter passing the values from the signals can be put together to a result string easily. The encoding of the output can also be set,
|
|
# which is shown by the two outputs in ASCII code and HEXByte code.
|
|
MacroResultStringASCII = BLC_getMacroResultString(channelHandle, macro_nr)
|
|
six.print_("Serial number: " + MacroResultStringASCII + "(ASCII Code)")
|
|
six.print_("")
|
|
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 6. Use of getsig/setsig for signal handling
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# Use of getsig and setsig with BLC_sendCommand()
|
|
# The BabyLIN commands getsig and setsig are responsible for reading and setting individual signals.
|
|
# The signal used is determined by the signal number. This can be found in the bus description of the SDF.
|
|
# The signal_flag can be used to determine at which time or event the signal is to be read out:
|
|
# signal_flag = 0x00, returns the last value written to the bus signal.
|
|
# signal_flag = 0x01, reset fresh flag and wait for fresh signal value appearing on bus.
|
|
# signal_flag = 0x02, return signal value as result, if fresh value is availble, otherwise returns RETCODE_OPERATION_PENDING
|
|
six.print_("Set the bus signals of brightness by setsig and getsig command")
|
|
signal_nr = 8
|
|
signal_flag = 0
|
|
index = 0
|
|
luminanceValue = 100
|
|
BLC_sendCommand(channelHandle, "getsig " + str(signal_nr) + " " + str(signal_flag) + ";")
|
|
if rc != 0:
|
|
six.print_("BLC command could not be executed.")
|
|
sys.exit(-1)
|
|
rc = BLC_lastAnswerHasData(channelHandle)
|
|
if rc == 0:
|
|
ByteValue = BLC_getAnswerByIndex(channelHandle, index)
|
|
six.print_("Current luminance configuration: " + str(ord(ByteValue)))
|
|
|
|
# Signal value luminance is set to 100 with BLC_sendCommand "setsig"
|
|
rc = BLC_sendCommand(channelHandle, "setsig " + str(signal_nr) + " " + str(luminanceValue) + ";")
|
|
if rc != 0:
|
|
six.print_("BLC command could not be executed.")
|
|
sys.exit(-1)
|
|
|
|
# Control setsig Command with readout the Signal value again via getsig
|
|
rc = BLC_sendCommand(channelHandle, "getsig " + str(signal_nr) + " " + str(signal_flag) + ";")
|
|
if rc != 0:
|
|
six.print_("BLC command could not be executed.")
|
|
sys.exit(-1)
|
|
rc = BLC_lastAnswerHasData(channelHandle)
|
|
if rc == 0:
|
|
ByteValue = BLC_getAnswerByIndex(channelHandle, index)
|
|
six.print_("Luminance increased to 100")
|
|
six.print_("Current luminance configuration: " + str(ord(ByteValue)))
|
|
six.print_("")
|
|
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 7. Frame registration and display of the framecallbacks
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# Here we will subscribe to get frames and write their data
|
|
# The disframe command can be used to subscribe to specific frames. These are determined by the frame ID.
|
|
# If you pass 0xff as parameter, a special case is executed and all frames defined in the SDf are subscribed.
|
|
# The frames are defined as a structure in the DLL and thus offer the possibility to display all information, such as the FrameID or the timestamp.
|
|
six.print_("Subscribe to Frames")
|
|
|
|
# Subscribe to frames
|
|
FrameIDForAllFrames = 0xff
|
|
rc = BLC_sendCommand(channelHandle, "disframe " + str(FrameIDForAllFrames) + " 1;")
|
|
if rc != 0:
|
|
six.print_("BLC command could not be executed.")
|
|
sys.exit(-1)
|
|
|
|
# the output of the callback will fill up the screen quickly
|
|
# press <ENTER> to see the incoming frames, and <ENTER> again
|
|
# to stop the output
|
|
try:
|
|
p = "Starting frame callback now...\n"
|
|
p += "Press <Enter> to start and stop"
|
|
input(p)
|
|
except Exception as e:
|
|
pass
|
|
|
|
# register the frame-callback
|
|
BLC_registerFrameCallback(channelHandle, framecallback)
|
|
|
|
try:
|
|
input("") # waiting for the next <enter>
|
|
except Exception as e:
|
|
pass
|
|
|
|
# de-register the frame-callback
|
|
BLC_registerFrameCallback(channelHandle, None)
|
|
|
|
# stop the LIN-bus
|
|
BLC_sendCommand(channelHandle, "stop;")
|
|
|
|
# close all devices. end of example.
|
|
BLC_closeAll()
|
|
break
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
# 8. Error handling
|
|
# ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
except BabyLIN.BabyLINException as e:
|
|
six.print_(e)
|
|
|
|
if __name__ == '__main__':
|
|
sdf, verbose = parse_arguments()
|
|
|
|
try:
|
|
main(sdf, verbose)
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|