Milk-v RISC-V
Sir, How are yhou ?
I installed the Misty on my MILK-V DUO S, i used the PIP
When i try to execute the bc --ini ./bc.ini
I am getting this
[root@milkv-duo]~# bc --ini ./bc.ini
Traceback (most recent call last):
File "/usr/bin/bc", line 577, in
Can you help me ?
Hi,
Please compile it on your architecture and install it.
https://github.com/riptideio/misty?tab=readme-ov-file#installation-and-usage-for-developers
That would make sure that the shared library is built for your system.
Thanks.
Bye, Raghavan V
Hi!!!!!!!!!!!!
The MILK-V Duo S only works with cross-compile...
Can you compile to me ?
got progress on cross-compile...
Please, what means this error ?
I want to use MSTP on ttyS1
thanks
[root@milkv-duo]~# bc --ini ./bc.ini
Initialized the socket
mac_address = 25
max master = 127
baud rate = 38400
max info frames = 1
RS485: Initializing /dev/ttyS1=success!
MS/TP MAC: 19
MS/TP Max_Master: 7F
MS/TP Max_Info_Frames: 1
mstp_path=ttyS1
Traceback (most recent call last):
File "/usr/bin/bc", line 577, in
I had to put some Static values to make it work...
I will do more tests soon
hi, I found a bacnet mtsp server, wrote in C++ https://github.com/chipkin/bacnetservermstpexamplecpp?tab=readme-ov-file i executed it...
C:\Users\Miguel\Desktop\bacnetservermstp>BACnetServerMSTPExample_x64_Release.exe COM15 9600 25 CAS BACnet Stack Server MSTP Example v0.0.2.0 https://github.com/chipkin/BACnetServerMSTPExampleCPP MSTP [serial port] [baud rate] [mac address]
FYI: Using comport=[COM15], Portnr=[14] FYI: Using macAddress=[25] FYI: Loading CAS BACnet Stack functions... OK FYI: CAS BACnet Stack version: 3.19.0.1311 FYI: Connecting serial resource to serial port. baudrate=[9600], ... OK OK, Connected to port FYI: Registering the callback Functions with the CAS BACnet Stack Setting up server device. device.instance=[389999] Created Device. Enabling WriteProperty service... OK Enabling device optional properties. Max_info_frames, max_master... OK FYI: Sending I-AM broadcast FYI: Entering main loop...
On bacnet client...
witch parameter i put on bacnet prompt >
?
My milk-v is connected (using RS485) to the PC...
Thanks!
I see that agent was off... then i changed the Milk-Duo S to run as ARM, not RISC-V... And...
getting goood progress
Hi, is there some python example, where i can read some analogvalue from BACSERVER, but not using the console. but directly on python source code ?
Very good progress.
I recall doing a bacnet client without the Console. I tried looking for it, but could not find it.
But here is the broad idea.
(1) Change the LocalDevice initialization to not use the ini. You can pass the parameters directly.
this_device = LocalDeviceObject(ini=args.ini, **mstp_args)
(2) Remove creating the console. You dont need it anymore.
# make a console
this_console = BacnetClientConsoleCmd()
if _debug: _log.debug(" - this_console: %r", this_console)
(3) Now after you make the above changes. You will not have a way to Trigger it, right ? So you can use the PulseTask like this and trigger it.
class PulseTask(RecurringTask):
def __init__(self, app, interval=None, offset=None):
super().__init__(interval, offset)
self.install_task()
self.app = app
def process_task(self):
self.app.fetch_values()
# Use it in the main like this
# make a simple application
app = BACnetClientApplication(address)
app.start()
PulseTask(app, interval=10 * 1000)
The way I tested it was using server from bacnet-stack (https://github.com/bacnet-stack/bacnet-stack).
The bacnet-stack also has a binary bacepics which lists all the objects and the current values.
Can` you fix this code that i tried ?
from misty.mstplib import MSTPSimpleApplication
from bacpypes.object import get_datatype
from bacpypes.apdu import ReadPropertyRequest
from bacpypes.primitivedata import ObjectIdentifier, Unsigned, Real
from bacpypes.constructeddata import Array, Any
from bacpypes.pdu import Address
from bacpypes.local.device import LocalDeviceObject
import time
class MyMSTPClient(MSTPSimpleApplication):
def __init__(self, ini_file, *args, **kwargs):
# ini parsing is done by MSTPSimpleApplication base
super().__init__(ini_file, *args, **kwargs)
def who_is(self, low_limit=None, high_limit=None):
# Send Who-Is to discover devices
self.request_whois(low_limit, high_limit)
def read_property(self, device_address, obj_type, obj_instance, prop_id):
# Build ReadProperty request
object_id = ObjectIdentifier(obj_type, obj_instance)
apdu = ReadPropertyRequest(
objectIdentifier=object_id,
propertyIdentifier=prop_id
)
# Destination: device via MS/TP
dest = Address(device_address)
iocb = self.request(apdu, destination=dest)
# Wait / poll for response
while not iocb.done:
time.sleep(0.1)
if iocb.ioError:
raise RuntimeError(f"I/O Error: {iocb.ioError}")
return iocb.ioResponse
def main():
# Path to your ini
ini = "client.ini"
# Create local device parameters
# (MSTP-specific args passed via ini or via kwargs)
local_device = LocalDeviceObject(ini=ini)
app = MyMSTPClient(ini_file=ini, localDevice=local_device)
# Discover devices on the MSTP network
print("Sending Who-Is...")
app.who_is()
# Wait some time to collect Who-Is / I-Am responses
time.sleep(5)
# Suppose we discovered a device at MSTP MAC address 10
target_mac = 10
obj_type = 'analogInput' # or 'binaryOutput' etc.
obj_id = 1
prop = 'presentValue'
try:
print(f"Reading {obj_type} {obj_id} presentValue from device {target_mac}")
response = app.read_property(target_mac, obj_type, obj_id, prop)
# response is a BACpypes constructed response object
print("Response:", response)
except Exception as e:
print("Error reading property:", e)
# Graceful close if needed
app.shutdown()
if __name__ == "__main__":
main()
client.ini
[root@milkv-duo]~# cat client.ini Cpypes] objectName: MSTPClient address: 25 interface: /dev/ttyS1 max_masters: 127 baudrate: 38400 maxinfo: 1 objectIdentifier: 599 maxApduLengthAccepted: 1024 segmentationSupported: segmentedBoth vendorIdentifier: 15
Thanks to the help
then we can include in you samples :)
@raghavan97 Or send your complete example...:) Thank you again!
In parallel, i did a Python app that make communication with console using PIPE
Communication cool with 2 mstp DEVICES
Hi,
I just added a non-console polling bacnet client in the samples. It is self contained. You can pass the device path of the serial device , baudrate etc , it will do whois, find out the points and keep polling them every 10 seconds. It prints and also writes it into a CSV.
You might find it useful.
I would suggest that you start with a new virtual environment, clone and do
pip install .
and run
python samples/polling_bac_client.py
Please note that the directories have been moved around.
Please let me know how it goes
Hi, Please have a NEW virtual environment where you dont have any of the old builds.
(1) clone the misty project
(2) at the root do
pip install .
This will build the sources and the install it in the environment
(3) Try running the sample
python samples/polling_bac_client.py
You need to go to a new virtual environment first where you have nothing installed. This is typically done by running python -m venv my_venv source my_venv/bin/activate
git clone https://github.com/riptideio/misty.git cd misty
builds the C library and installs in editable mode
python -m pip install .
see what parameters you can give (e.g. interface path /dev/ttyS5 or
whatever) python samples/polling_bac_client.py --help
most likely parameters (assuming you are doing 38400 baud rate )
python samples/polling_bac_client.py --interface /dev/ttywhatever
On Mon, Oct 6, 2025 at 7:07 AM tcpipchip @.***> wrote:
tcpipchip left a comment (riptideio/misty#23) https://github.com/riptideio/misty/issues/23#issuecomment-3369646883
and... must i rebuild the path /src ?
— Reply to this email directly, view it on GitHub https://github.com/riptideio/misty/issues/23#issuecomment-3369646883, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACCAWYKGDYWB6ASCFX3JG633WHBVLAVCNFSM6AAAAACFZIDOC2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTGNRZGY2DMOBYGM . You are receiving this because you were mentioned.Message ID: @.***>
Remember that samples/polling_bac_client.py does NOT make use of the ini file. It only takes the parameters from command line
Hi @raghavan97 :)
I had to make some changes on MILK-V to make work....because MILK-V Duo does not have make and gcc..etc
See if this feedback is ok on polling example
Address: 25 Interface: /dev/ttyS1 Baudrate: 38400 'DEVICE_DB' {} 'SNAPSHOT' {} Object list count = 83, expected = 83 object list complete Object list count = 6, expected = 6 object list complete 'DEVICE_DB' {4000: {'address': '0', 'maxAPDULengthAccepted': 480, 'object_list': [('device', 4000), ('analogInput', 1), ('analogOutput', 1), ('analogValue', 1), ('analogValue', 2), ('analogValue', 3), ('binaryInput', 1), ('binaryOutput', 1), ('binaryValue', 1), ('binaryValue', 2), ('calendar', 1), ('command', 1), ('eventEnrollment', 1), ('eventEnrollment', 2), ('eventEnrollment', 3), ('eventEnrollment', 4), ('eventEnrollment', 5), ('eventEnrollment', 6), ('eventEnrollment', 7), ('eventEnrollment', 8), ('eventEnrollment', 9), ('eventEnrollment', 10), ('eventEnrollment', 11), ('eventEnrollment', 12), ('eventEnrollment', 13), ('eventEnrollment', 14), ('eventEnrollment', 15), ('eventEnrollment', 16), ('file', 1), ('file', 2), ('group', 1), ('loop', 1), ('multiStateInput', 1), ('multiStateOutput', 1), ('notificationClass', 1), ('program', 1), ('program', 2), ('program', 3), ('program', 4), ('program', 5), ('program', 6), ('program', 7), ('program', 8), ('schedule', 1), ('schedule', 2), ('averaging', 1), ('multiStateValue', 1), ('multiStateValue', 2), ('trendLog', 1), ('lifeSafetyPoint', 1), ('lifeSafetyZone', 1), ('accumulator', 1), ('pulseConverter', 1), ('pulseConverter', 2), ('eventLog', 1), ('globalGroup', 1), ('trendLogMultiple', 1), ('loadControl', 1), ('structuredView', 1), ('accessDoor', 1), ('accessCredential', 1), ('accessPoint', 1), ('accessRights', 1), ('accessUser', 1), ('accessZone', 1), ('credentialDataInput', 1), ('networkSecurity', 1), ('bitstringValue', 1), ('characterstringValue', 1), ('datePatternValue', 1), ('dateValue', 1), ('datetimePatternValue', 1), ('datetimeValue', 1), ('integerValue', 1), ('largeAnalogValue', 1), ('octetstringValue', 1), ('positiveIntegerValue', 1), ('timePatternValue', 1), ('timeValue', 1), ('notificationForwarder', 1), ('alertEnrollment', 1), ('channel', 1), ('lightingOutput', 1)], 'object_list_complete': True, 'segmentationSupported': 'segmentedBoth', 'vendorID': 4}, 4444: {'address': '4004:0x00115c', 'maxAPDULengthAccepted': 1476, 'object_list': [('device', 4444), ('analogValue', 1), ('binaryValue', 1), ('notificationClass', 2), ('program', 1), ('multiStateValue', 1001)], 'object_list_complete': True, 'segmentationSupported': 'segmentedBoth', 'vendorID': 4}} 'SNAPSHOT' {4000: {('analogInput', 1): {'ackedTransitions': [1, 1, 1], 'covIncrement': 0.0, 'deadband': 1.0, 'description': 'Test Analog Input 1', 'deviceType': 'Simulated Sensor using PG1', 'eventAlgorithmInhibit': False, 'eventAlgorithmInhibitRef': {'objectIdentifier': ('binaryValue', 4194303), 'propertyIdentifier': 'presentValue'}, 'eventDetectionEnable': True, 'eventEnable': [0, 0, 0], 'eventMessageTexts': ['', '', ''], 'eventState': 'normal', 'eventTimeStamps': [{'time': (255, 255, 255, 255)}, {'sequenceNumber': 0}, {'dateTime': {'date': (255, 255, 255, 255), 'time': (255, 255, 255, 255)}}], 'highLimit': 75.0, 'limitEnable': [0, 0], 'lowLimit': 65.0, 'maxPresValue': 100.0, 'minPresValue': 0.0, 'notificationClass': 1, 'notifyType': 'alarm', 'objectIdentifier': ('analogInput', 1), 'objectName': 'AI1', 'objectType': 'analogInput', 'outOfService': False, 'presentValue': 91.0, 'profileName': '0-Object-AnalogInput', 'reliability': 'noFaultDetected', 'reliabilityEvaluationInhibit': False, 'resolution': 1.0, 'statusFlags': [0, 0, 0, 0], 'timeDelay': 0, 'timeDelayNormal': 0, 'units': 'degreesFahrenheit', 'updateInterval': 100}, ('analogOutput', 1): {'ackedTransitions': [1, 1, 1], 'covIncrement': 0.0, 'deadband': 5.0, 'description': 'Test Analog Output 1', 'deviceType': 'Unsimulated', 'eventEnable': [0, 0, 0], 'eventState': 'normal', 'eventTimeStamps': [{'time': (255, 255, 255, 255)}, {'sequenceNumber': 0}, {'dateTime': {'date': (255, 255, 255, 255), 'time': (255, 255, 255, 255)}}], 'highLimit': 50.0, 'limitEnable': [0, 0], 'lowLimit': -50.0, 'maxPresValue': 100.0, 'minPresValue': -100.0, 'notificationClass': 1, 'notifyType': 'alarm', 'objectIdentifier': ('analogOutput', 1), 'objectName': 'AO1', 'objectType': 'analogOutput', 'outOfService': False, 'presentValue': 65.0, 'priorityArray': [{'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'real': 65.0}], 'profileName': '0-Object-AnalogOutput', 'reliability': 'noFaultDetected', 'relinquishDefault': 0.0, 'resolution': 1.0, 'statusFlags': [0, 0, 0, 0], 'timeDelay': 0, 'units': 'noUnits'}}, 4444: {('analogValue', 1): {'ackedTransitions': [1, 1, 1], 'covIncrement': 0.0, 'deadband': 10.0, 'description': 'Test Analog Value 1', 'eventEnable': [0, 0, 0], 'eventState': 'normal', 'eventTimeStamps': [{'time': (255, 255, 255, 255)}, {'sequenceNumber': 0}, {'dateTime': {'date': (255, 255, 255, 255), 'time': (255, 255, 255, 255)}}], 'highLimit': 100.0, 'limitEnable': [0, 0], 'lowLimit': -100.0, 'notificationClass': 2, 'notifyType': 'alarm', 'objectIdentifier': ('analogValue', 1), 'objectName': 'AV1', 'objectType': 'analogValue', 'outOfService': False, 'presentValue': 95.0, 'priorityArray': [{'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}], 'profileName': '4-Object-AnalogValue', 'reliability': 'noFaultDetected', 'relinquishDefault': 0.0, 'statusFlags': [0, 0, 0, 0], 'timeDelay': 0, 'units': 'noUnits'}}} 'DEVICE_DB' {4000: {'address': '0', 'maxAPDULengthAccepted': 480, 'object_list': [('device', 4000), ('analogInput', 1), ('analogOutput', 1), ('analogValue', 1), ('analogValue', 2), ('analogValue', 3), ('binaryInput', 1), ('binaryOutput', 1), ('binaryValue', 1), ('binaryValue', 2), ('calendar', 1), ('command', 1), ('eventEnrollment', 1), ('eventEnrollment', 2), ('eventEnrollment', 3), ('eventEnrollment', 4), ('eventEnrollment', 5), ('eventEnrollment', 6), ('eventEnrollment', 7), ('eventEnrollment', 8), ('eventEnrollment', 9), ('eventEnrollment', 10), ('eventEnrollment', 11), ('eventEnrollment', 12), ('eventEnrollment', 13), ('eventEnrollment', 14), ('eventEnrollment', 15), ('eventEnrollment', 16), ('file', 1), ('file', 2), ('group', 1), ('loop', 1), ('multiStateInput', 1), ('multiStateOutput', 1), ('notificationClass', 1), ('program', 1), ('program', 2), ('program', 3), ('program', 4), ('program', 5), ('program', 6), ('program', 7), ('program', 8), ('schedule', 1), ('schedule', 2), ('averaging', 1), ('multiStateValue', 1), ('multiStateValue', 2), ('trendLog', 1), ('lifeSafetyPoint', 1), ('lifeSafetyZone', 1), ('accumulator', 1), ('pulseConverter', 1), ('pulseConverter', 2), ('eventLog', 1), ('globalGroup', 1), ('trendLogMultiple', 1), ('loadControl', 1), ('structuredView', 1), ('accessDoor', 1), ('accessCredential', 1), ('accessPoint', 1), ('accessRights', 1), ('accessUser', 1), ('accessZone', 1), ('credentialDataInput', 1), ('networkSecurity', 1), ('bitstringValue', 1), ('characterstringValue', 1), ('datePatternValue', 1), ('dateValue', 1), ('datetimePatternValue', 1), ('datetimeValue', 1), ('integerValue', 1), ('largeAnalogValue', 1), ('octetstringValue', 1), ('positiveIntegerValue', 1), ('timePatternValue', 1), ('timeValue', 1), ('notificationForwarder', 1), ('alertEnrollment', 1), ('channel', 1), ('lightingOutput', 1)], 'object_list_complete': True, 'segmentationSupported': 'segmentedBoth', 'vendorID': 4}, 4444: {'address': '4004:0x00115c', 'maxAPDULengthAccepted': 1476, 'object_list': [('device', 4444), ('analogValue', 1), ('binaryValue', 1), ('notificationClass', 2), ('program', 1), ('multiStateValue', 1001)], 'object_list_complete': False, 'segmentationSupported': 'segmentedBoth', 'vendorID': 4}} 'SNAPSHOT' {4000: {('analogInput', 1): {'ackedTransitions': [1, 1, 1], 'covIncrement': 0.0, 'deadband': 1.0, 'description': 'Test Analog Input 1', 'deviceType': 'Simulated Sensor using PG1', 'eventAlgorithmInhibit': False, 'eventAlgorithmInhibitRef': {'objectIdentifier': ('binaryValue', 4194303), 'propertyIdentifier': 'presentValue'}, 'eventDetectionEnable': True, 'eventEnable': [0, 0, 0], 'eventMessageTexts': ['', '', ''], 'eventState': 'normal', 'eventTimeStamps': [{'time': (255, 255, 255, 255)}, {'sequenceNumber': 0}, {'dateTime': {'date': (255, 255, 255, 255), 'time': (255, 255, 255, 255)}}], 'highLimit': 75.0, 'limitEnable': [0, 0], 'lowLimit': 65.0, 'maxPresValue': 100.0, 'minPresValue': 0.0, 'notificationClass': 1, 'notifyType': 'alarm', 'objectIdentifier': ('analogInput', 1), 'objectName': 'AI1', 'objectType': 'analogInput', 'outOfService': False, 'presentValue': 91.0, 'profileName': '0-Object-AnalogInput', 'reliability': 'noFaultDetected', 'reliabilityEvaluationInhibit': False, 'resolution': 1.0, 'statusFlags': [0, 0, 0, 0], 'timeDelay': 0, 'timeDelayNormal': 0, 'units': 'degreesFahrenheit', 'updateInterval': 100}, ('analogOutput', 1): {'ackedTransitions': [1, 1, 1], 'covIncrement': 0.0, 'deadband': 5.0, 'description': 'Test Analog Output 1', 'deviceType': 'Unsimulated', 'eventEnable': [0, 0, 0], 'eventState': 'normal', 'eventTimeStamps': [{'time': (255, 255, 255, 255)}, {'sequenceNumber': 0}, {'dateTime': {'date': (255, 255, 255, 255), 'time': (255, 255, 255, 255)}}], 'highLimit': 50.0, 'limitEnable': [0, 0], 'lowLimit': -50.0, 'maxPresValue': 100.0, 'minPresValue': -100.0, 'notificationClass': 1, 'notifyType': 'alarm', 'objectIdentifier': ('analogOutput', 1), 'objectName': 'AO1', 'objectType': 'analogOutput', 'outOfService': False, 'presentValue': 65.0, 'priorityArray': [{'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'real': 65.0}], 'profileName': '0-Object-AnalogOutput', 'reliability': 'noFaultDetected', 'relinquishDefault': 0.0, 'resolution': 1.0, 'statusFlags': [0, 0, 0, 0], 'timeDelay': 0, 'units': 'noUnits'}, ('analogValue', 1): {'covIncrement': 0.0, 'description': 'Test Analog Value 1 - PID ' 'controlled variable', 'eventState': 'normal', 'maxPresValue': 100.0, 'minPresValue': 0.0, 'objectIdentifier': ('analogValue', 1), 'objectName': 'AV1', 'objectType': 'analogValue', 'outOfService': False, 'presentValue': 73.03, 'priorityArray': [{'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'null': ()}, {'real': 73.02879333496094}], 'profileName': '0-Object-AnalogValue', 'reliability': 'noFaultDetected', 'relinquishDefault': 68.0, 'resolution': 1.0, 'statusFlags': [0, 0, 0, 0], 'units': 'degreesFahrenheit'}, . . . attached the CSV
This looks fabulous. You now have a non-console based application that will keep polling and getting the values. I hope this is what you were chasing.
Yes, very very nice!!!!!!
There have to be more device points values in the snapshot ?
Can you run it until it says
Wrote records.
and stops scrolling on the screen, do a ctrl-C . It will stop the program.
At that point take the snapshot.csv and send it over here.
I think there would be around 80 rows for 4000 and around 6 for 4444
do you want that i do some more tests ?
Not really.It is all good.
Thanks