OmstNET released to GitHub

Python OmstNET for Linux

I have posted OmstNET Python3.4 for Linux to GitHub.

OmstNET communicates in ASCII mode over serial ports in Linux. I have tested it at 115,200 on both hardware and two different USB serial port devices under Linux Mint 17.3 on an AMD A10 PC. Refer to the ReadMe.pdf file for information on running the software along with some code samples and example gnome terminal session printouts.


Thank-you for this. Awesome stuff.

I have binary mode working but am still messing with crc calculations and trying to predict the device baud jumpers and system options bits from the response packets. The unit sends a nak 2 error in response to a command with the wrong crc. I should be able to use the crc it delivered in the nak to pick apart it’s system options settings, ie was it initialized with 0 or -1, is it ccitt or crc16, and forward or reverse. Not working yet, by almost there.

The binary transfer is a bit inefficient in Linux because at least my version does not allow mark and space parity making me twiddle the parity mode between odd and even to meet the transmit requirements for the 9th bit. I do see that there is at least one avr usb to 9 bit converter out there which requires sending 16 bits over usb for each serial byte sent so that the msb can contain the 9th address flag bit. However, at least I can test binary mode.

I have put the binary mode updates on GitHub. I tested by running the verify_commands function in I changed the crc and binary mode jumpers on my B3000 and cycled power to check out the 4 possible combinations.

Refer to ReadMe.pdf for particulars. However, my Linux Mint 17.3 does not support CMSPAR so I have to call termios to change the parity bit for each byte in the command to keep the address parity bit a mark, and the data parity bit a space.

Thinking about it, if I were to make a USB to 9 bit converter specifically for Mistic, I would have the PC send Mistic ASCII packets. The USB to serial converter would parse the Mistic ASCII packets, and convert them on the fly to Mistic binary packets and send them out the 9 bit UART.

Bought a B3000-ENET off of EBAY. Plugged it in to my SNAPB12M rack, powered it up, set IP address, and have successfully sent a ‘POWER UP CLEAR’ message and parsed the response. So it may be baby steps, but I am now embarking on a Python interface via OptoMMP as time allows. It will give me a chance to move up from serial and learn some sockets stuff in Python.

Hi Doug, it’s awesome to hear you’re getting into OptoMMP with Python, that’s what I’ve been working with this past week! Here’s a link to my in-development github repo that has some scripts,,, and, that might help show you one way of doing things. I’ll post them with more substantial documentation soon, but until then feel free to ask any questions.
I hope it helps!

I have the ReadQuadlet, ReadBlock, WriteQuadlet, and WriteBlock working in my Python code. I got some failures reading values such as:

  • FFFF F030 0080 20 S-ZT Device’s part number (string)
  • FFFF F030 00A0 10 S-ZT Firmware version date
  • FFFF F030 00B0 10 S-ZT Firmware version time

so I launched IoManager.

It turns out that not all memory addresses described in the OptoMMP users guide are implemented in my B3000-ENET.

I haven’t found documentation for the B3000-ENET that specifies which memory map values are in fact supported. I would think this would be available somewhere. I would not expect to have to iterate through the entire OptoMMP spec trying each address and looking for failures to determine this.

I can use my Python OptoMMP code to configure output points to type 0x180 and then turn them on or off individually. But I don’t seem to get a bank read/write through addresses in the 0xfffff050xxxx range to work, even though I think I am getting an rcode 0 response. My packet looks fine as far as I can tell but the outputs don’t change. IoManager doesn’t show this address range, but it does show bank 0xfffff040xxxx reads.

I increment tl with each command and the response follows this value, so I have to assume the rcode=0 in the response packet is in fact an ack of the command. I have tried sending 0xffffffffffffffff, ie: set all points on, and also set all points off but the points I have activated individually do not change state. It makes me thing the B3000-ENET ignores write requests to the digital bank for some reason.

I am talking to a B3000-ENET. I’d appreciate info on B3000-ENET OptoMMP implementation specifics that I can check to make sure I don’t spin my wheels trying to troubleshoot issues when reading/writing to unsupported mmap regions.

Here is some output.

  • points 0,1,2,3,8,9,10,11 are set as outputs and turned on.
  • digital bank read to show state
  • digital bank write to try to clear
  • digitl bank read to test clear
  • digital bank write to try to set
  • digital bank read to see if set

WriteQuadlet b’\x00\x00\x00\x00\x00\x00\xff\xff\xf0\xc0\x00\x04\x00\x00\x01\x80’
WriteResponse b’\x00\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00\x04\x00\x00\x00\xff\xff\xf0\x90\x00\x00\x00\x00\x00\x01’
WriteResponse b’\x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00\x08\x00\x00\x00\xff\xff\xf0\xc0\x00D\x00\x00\x01\x80’
WriteResponse b’\x00\x00\x08 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00\x0c\x00\x00\x00\xff\xff\xf0\x90\x00@\x00\x00\x00\x01’
WriteResponse b’\x00\x00\x0c \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00\x10\x00\x00\x00\xff\xff\xf0\xc0\x00\x84\x00\x00\x01\x80’
WriteResponse b’\x00\x00\x10 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00\x14\x00\x00\x00\xff\xff\xf0\x90\x00\x80\x00\x00\x00\x01’
WriteResponse b’\x00\x00\x14 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00\x18\x00\x00\x00\xff\xff\xf0\xc0\x00\xc4\x00\x00\x01\x80’
WriteResponse b’\x00\x00\x18 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00\x1c\x00\x00\x00\xff\xff\xf0\x90\x00\xc0\x00\x00\x00\x01’
WriteResponse b’\x00\x00\x1c \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00 \x00\x00\x00\xff\xff\xf0\xc0\x02\x04\x00\x00\x01\x80’
WriteResponse b’\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00$\x00\x00\x00\xff\xff\xf0\x90\x02\x00\x00\x00\x00\x01’
WriteResponse b’\x00\x00$ \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00(\x00\x00\x00\xff\xff\xf0\xc0\x02D\x00\x00\x01\x80’
WriteResponse b’\x00\x00( \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00,\x00\x00\x00\xff\xff\xf0\x90\x02@\x00\x00\x00\x01’
WriteResponse b’\x00\x00, \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x000\x00\x00\x00\xff\xff\xf0\xc0\x02\x84\x00\x00\x01\x80’
WriteResponse b’\x00\x000 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x004\x00\x00\x00\xff\xff\xf0\x90\x02\x80\x00\x00\x00\x01’
WriteResponse b’\x00\x004 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x008\x00\x00\x00\xff\xff\xf0\xc0\x02\xc4\x00\x00\x01\x80’
WriteResponse b’\x00\x008 \x00\x00\x00\x00\x00\x00\x00\x00’
WriteQuadlet b’\x00\x00<\x00\x00\x00\xff\xff\xf0\x90\x02\xc0\x00\x00\x00\x01’
WriteResponse b’\x00\x00< \x00\x00\x00\x00\x00\x00\x00\x00’
ReadBlock b’\x00\x00@P\x00\x00\xff\xff\xf0@\x00\x00\x00\x08\x00\x00’
ReadBlockResponse b’\x00\x00@p\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x0f’
WriteBlock b’\x00\x00D\x00\x00\x00\xff\xff\xf0P\x00\x08\x00\x08\x00\x00
WriteResponse b’\x00\x00D \x00\x00\x00\x00\x00\x00\x00\x00’
WriteResponse(tl=17, tcode=2, rcode=0)
ReadBlock b’\x00\x00HP\x00\x00\xff\xff\xf0@\x00\x00\x00\x08\x00\x00’
ReadBlockResponse b’\x00\x00Hp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x0f’
WriteBlock b’\x00\x00L\x00\x00\x00\xff\xff\xf0P\x00\x00\x00\x08\x00\x00
WriteResponse b’\x00\x00L \x00\x00\x00\x00\x00\x00\x00\x00’
WriteResponse(tl=19, tcode=2, rcode=0)
ReadBlock b’\x00\x00PP\x00\x00\xff\xff\xf0@\x00\x00\x00\x08\x00\x00’
ReadBlockResponse b’\x00\x00Pp\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x0f\x0f\x0f\x0f’

The first thing I would try is opening the device in PAC Manager and check out the address ranges there specifically. It is certainly possible that the bank read/write area is not supported for the B3000-ENET – as far as I’m aware all information regarding OptoMMP is in the Protocol Guide or can be found in Manager.

I’m just working with individual points on the groov EPIC using MMP, but still, I don’t see any problems with your quadlet requests. After that though, in your block requests, are those the entire packages? I’m not seeing what’s going on behind the scenes here but the fourth byte looks like it’s set to zero, where write block requests should have a transaction code of 1 in the upper half of the byte – so \x10 in hex. Could that be causing an issue?

That said, if the guide, Manager, and your testing don’t point towards this area working, I would say that it’s likely not a supported feature.

Figured it out, and it was in fact the transaction code. I had improperly set the tcode for write block. The confusing thing is that it was in fact writing something to memory based on ioManager, which was incorrect. Since the packet was improperly formatted, I would have expected a failure response, but not so. So I have finally gotten a 1 hz timer routine working off of timer events.

One of the problems in developing custom stuff is typos in the manuals. On page 69 the turn on digital points I think is missing the two extended tcode bytes between the length and data field based on the packet description preceeding it. 000004100000FFFFF0500000000800000000FFFFFFAA

At first I trimmed these out of my packets thinking there was an error in the packet, until I spotted the tcode issue, then I had to put them back to get it to work.

I see that the B3000-ENET should support Pulse generation 'N pulses, continuous
square wave, on-pulse, off-pulse’ but I have not as of yet figured out where in the OptoMMP guide the mmap location for this can be found.

If you let @GrayChurch.Opto22 know about it, it will get fixed pretty much right away.


He’s been most helpful in the past, but since I typically play with older stuff, I try not to bother him too much, as it typically involves multiple individuals trying to refresh themselves on how things worked in the past.

1 Like

@philip and @dougm—Thanks for letting me know. I’ll look into it. And don’t hesitate to let us know, even if it’s older stuff.

I’ve been dealing with false acknowledgement of bad MMP requests as well; you’re not alone, it does make debugging awkward at times but I’m glad you were able to get it working.

Thanks for letting us know about the typeo, I’ll coordinate with @GrayChurch.Opto22 to make sure her update matches the template. Those templates really are the bread and butter of the protocol, just in general I recommend basing your code off of those, for me at least it helps to see the individual bits spaced out so I know what goes where in my array.

In regards to your question about N pulse generation, MMP is not exposed to that interface, so you’ll need to use PAC Control point configuration or PAC Control commands to set that feature up.

1 Like


I updated the OptoMMP Protocol Guide (form 1465) and posted it on the website.
You may have to do a Ctrl+F5 to clear the cache and get the latest version.

1 Like