Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Cube

Pages: [1] 2 3 ... 6
1
V_Buscom / Re: Modbus Data Blocks
« on: December 04, 2018, 08:47:26 PM »
It would appear that I've just somewhat recreated this post (though less eloquently.) Sigh. I guess it's good that I'm finally getting back around to it...

2
V_Buscom / Multiple RTU's, single Data Blocks
« on: December 04, 2018, 08:45:06 PM »
I am trying to build a bit of a monster. Or at least, something that could be very VERY cool. Part of this process sees me learning a lot about MODBUS. Indeed, I'd never really touched it before I started trying to write an interface for it. Now I have a specific need -- a problem to solve -- and it is starting to take shape.

Here's the situation.

I have a single modbus device that only accepts one TCP/IP connection. It has multiple data blocks (registers) that it maintains, and that I sometimes need to update. Presently this device (master) is being connected to by a third party client. I need that third party to be able to maintain it's connection to this device, but I also need to get a connection to it. What I have devised and am trying to implement is this: A kind of multi-connection modbus datablock architecture. Or, put another way, a Modbus Splitter.

Basically I will create my own datablocks in Buscom that will mimic the real ones in the master device. Then I will connect myself as a slave to that master and poll it's registers at the same interval as the original client did. I will then ALSO provide a master and point the third party to me instead of the original master, thus putting Buscom in the middle, but it will actually be serving it's data out of the same datablock that is being polled from the original master. Now I can connect potentially any number of clients to me and share this same data with them as they please. Using pthread rwlocks should ensure data integrity while allowing reads from a significant number of clients simultaneously. (Really, I only need one extra connection.)

Now for the tun part -- doing it!

3
... So I implemented the multiple base object name feature, tested it, got it all 100% and then realized that the modbus command handlers were already designed to be prefixed with modbus on every command (so basically option number one.)

In any event, we've added a new feature to Buscom that could be useful down the road.

4
I was very excited about the new plugin architecture. It was going very well, and several of the more "built-in" modules had been successfully converted to full blown standalone ones without much ado - including Lenel OnGuard's plugin and the one I'd created for talking to Simplex panels (well, listening to would be nearer the mark.) I started attempting to rebuild the MODBUS module as a plugin, and then decided to try to bring as much of the original code over as possible. That, however, is when I ran into the first new snag in this plugin architecture. The Base Object Name.

In Buscom, you have some core functionality that is accessed by top level items through vterm (the command line interface) such as channel or xmq. When you load a plugin, the plugin adds it's own base object as part of the linkage process, so that buscom's command handler knows what commands to pass on to the plugin's command handling routines. In the past, these have all been single items, but with the modbus module, I had designated multiple top level objects, including rtu and datablocks. This presents a problem, since you can at present only have one top level base object name.

There are a couple of ways to work around this:
  • Prefix all commands with modbus - IE: modbus rtu 1 show
  • Modify the base object designation to allow multiple items separated by a delimiter - IE: modbus|rtu|datablock
  • Something else?

Personally, I am leaning towards the second option because it keeps in line with the rest of Venturii's norms, and offers the most flexibility for this and future plugins. It does, of course, require modification to the buscom code itself to strip out and parse the multiple base object names, but that is minor and trivial, really. Good. I'm glad that's settled.

5
V_Buscom / Re: Asterisk Plugin Eyed on the Horizon
« on: May 17, 2018, 07:46:22 AM »
I thought I'd spend a few minutes outlining some of the features I'd like to implement with this Buscom Plugin.
  • Incoming Calls enter Venturii as Events
  • Ring Indicator, Voice Mail Waiting Indicator, Call Waiting Indicators all enumerate as VINTs that can be acted on from Decider and/or the web-based user interfaces
  • Ability to initiate calls from Venturii / Decider / Web Interface

These are just a few of the things I have been mulling about, and I don't think it would take much to implement them - especially now with the plugin architecture of Buscom.

6
V_Buscom / Re: Modbus Data Blocks
« on: May 16, 2018, 07:37:17 PM »
The Plot And Problem Both Thicken

The Modbus slave driver (interesting function categorization) utilizes the modbus_mapping_t structure type to contain each of the four types of data it can process: bits, input bits, registers and input registers. Each of these point to a contiguous block of memory allocated of either uint8_t or uint16_t, depending on the bits or bytes parts. The way I have my data blocks set up, they need not necessarily be contiguous nor present necessarily. This creates a problem though, when I try to blend the two systems of storing these data types together.

Thinking It Through

Because I want to be able to have multiple slaves serve data off the same block, we have the conundrum of where that block resides. On the one hand I could create a modbus_mapping_t structure within the RTU structure of each virtual Slave RTU, and could cross-link other RTU masters with that block, along with the DataBlocks to pull the VINT data from them. Maybe a better solution is to create external modbus blocks. If I remove my concept of a datablock (which is really just a subset of the main block of data) and create raw blocks of data as the data blocks instead, we could point VINTs at them using the newly implemented value arrays. Imagine then, we create a datablock of, say, a thousand bits and a thousand bytes for each of the pairs of input and output coils and registers within our virtual RTU slave. Now we can point our modbus_reply() function to this block of data, or we can point multiple RTUs at it. Then, we create new construct - maybe called something like a Section, Tag or Subset - which contains a starting address and a length parameter, referencing one of our main blocks of data. This Section gets a single VINT for it's value, but it will make proper use of the array functionality of VINTs now that this has been implemented. We add a Device Status VINT for the entire section (since one is enough) and we have our access in and out of the global data blocks, satisfying both needs with efficiency!

 The one last piece of the puzzle is data concurrency; race conditions and how to prevent them. Since multiple virtual and/or real RTU devices may be accessing the same block of memory, how can we ensure only one uses it at a time, especially when the reply() function potentially blocks? We might be able to use 0 timeout values, gather up all the sockfd's from each RTU device and run them through our own select() call. For that matter, we might single-thread the entire modbus plugin, which would eliminate the need for the locks at all. Interesting. A little daunting, but very interesting...

7
V_Buscom / Asterisk Plugin Eyed on the Horizon
« on: May 16, 2018, 08:54:42 AM »
Last night I was reading through the API documentation for Asterisk, the free telephone service platform, and I believe there is a new plugin on the horizon for integrating with that system. Many (!!) years ago I set up an IBM XT computer with a Monochrome (green) display whose sole purpose was to open up a terminal, issue the AT+CID=1 command to a Hayes modem in one of it's many ISA slots and listen for the Caller ID data coming in off the phone line. Even then, it was perhaps overkill, but it was a rather convenient way to log incoming call history. Much later, early versions of Venturii had a Maestro module that provided similar logging of the call data, but also provided the ability to do things with this information by sending it to Decider. Thus we had a light that would flash whenever family called so we knew without having to get up if we should rush to answer the phone.

Now, having moved away from a land line and having a pure VOIP solution, my caller ID system still technically works, but I've had it in mind since the switch-over to integrate at an IP level to Asterisk itself. As it turns out, their AMI protocol (Asterisk Management Interface) appears to be just the ticket, allowing events to be reported through the connection and even calls to be originated and directed through this API. As with all things, it is only a matter of time now. :)

8
V_Buscom / Modbus Data Blocks
« on: May 16, 2018, 08:47:55 AM »
Originally my design was to have RTU devices own DataBlocks. DataBlocks are arrays of bytes which are either read from or written to by modbus commands. Each of these bits or bytes would have a corresponding VINT associated with it, and thus we could apply Venturii nomenclature to Modbus Remote Terminal Unit devices in a fairly sane way. This was all up and running and worked well, however as I've been working on this project my understanding of Modbus has grown and so too my desire to extend the functionality of this plugin even further.

The problem

We are integrating with a Modbus system that at present only accepts a single connection; subsequent connection attempts succeed but are immediately closed. When we disconnect the incumbent system, we can connect Buscom's Modbus plugin and interact with the Modbus devices through the connection, but this cuts off all access to the legacy system.

A Solution In The Works

I was talking to one of my colleagues about this problem, and he suggested we "Y-Connect" the TCP socket. Not a terrible idea, but because Modbus is a query/response system, it's not as simple to just cross-connect the thing like an NCC-1701 warp core. However the suggestion got me thinking, and the more I thought, the more I liked the idea that came to mind. What if, I thought, we open up the data blocks to more than one RTU device. We could even create slave RTU devices in the Buscom plugin, that would simply serve up data from one or more linked data blocks. In this way we could act as an intermediary between the existing Modbus equipment, legacy system, and continue to develop and interact with the hardware ourselves concurrently -- all on this same Modbus connection. In fact, this virtual data block could serve as an information for multiple RTU masters.

Using this topology we could shoe-horn the Buscom/Modbus plugin in between those systems. One RTU Master device would query the existing field hardware, update it's own copy of the registers & coils (stored in data blocks within the Bustom/Modbus plugin) and we would act as a slave to the legacy system which would poll [[us]] for updates. Our slave would serve up the correct coil and register data to the legacy host which would be none the wiser that it was talking to an intermediary now instead of the field hardware directly, and we can ourselves peek and poke at the data in situ.

9
V_Buscom / Lenel OnGuard Integrates with Venturii
« on: March 22, 2018, 05:30:56 PM »
Buscom now has a plugin to talk to Lenel OnGuard through DataConduIT. Of course, you need to buy a DataConduIT license from Lenel for your particular installation, but once you've laid out that chunk of cash, integrating your OnGuard Access Control System with Venturii is free. Here is what is presently supported:

  • Venturii automatically generates DeviceIDs and appropriate VINTs for all the Readers, Inputs and Outputs in the OnGuard System.
  • Reader Mode (Card Only, Locked, Unlocked, Card And PIN, PIN or Card, etc.) enumerates as a VINT with a source of Reader Mode.
  • Door Forced Open, Door Held Open, Door Forced Open Masked, and Door Held Open Masked annunciate as separate VINT Sources with the same names.
  • Access Control Doors can be opened from Venturii by sending a Desired Value of 1 to the corresponding "Open Door Command" VINT source.
  • Input status from all Reader Inputs and Alarm Panel inputs enumerate as a VINT.
  • Input Masked Status of all Reader Auxiliary Inputs and Alarm Panel Inputs enumerates as a VINT with a source Masked. Setting the desired value of this VINT will control the Masked state of the corresponding Input.
  • Output status from all Reader Auxiliary Outputs and Alarm Panel Outputs enumerate as a VINT. Setting the Desired Value of this VINT controls the output (0=De-Energize, 1=Energize, 2=Pulse).

More features are coming soon! This means that you can use any of the web-based user interfaces to view the status of various points within your Lenel OnGuard Access Control System, or you can create new ones with the new User Interface System, code named ProximaVenturii. More details on that will also be coming soon!

10
Decider / Re: New Feature - TORX Time Definitions
« on: February 20, 2018, 04:18:07 PM »
I saw this topic here and wanted to give some feedback on it, mostly for posterity. This feature I use every day, and is probably one of the best features within Decider's time management system. I have it automatically turning off all the lights in the house after everyone's gone to work, I have it acting as a thermostat for my garage with some calculations and comparisons, I have it watering the lawn, gardens and hanging planters at the correct times and with the correct amount of water - it is a VERY versatile feature!

11
Decider / Websockets JSON and Web UI Control Surface Pages
« on: February 20, 2018, 04:16:03 PM »
I re-implemented a function today at the request of JH whereby upon registration of one or more VINTs for a Websocket session, Decider will send the current values and Device Status of all registered VINTs to the client in a single JSON object (an array) like so:

Sample Request:
Code: [Select]
{"RegisterVUIDs":["1","5","9"]}
Sample Response:
Code: [Select]
{"VintValues":[
   {"VUID":1,"DeviceStatus":1,"Value":2000},
   {"VUID":5,"DeviceStatus":1,"Value":2000},
   {"VUID":9,"DeviceStatus":1,"Value":2000}
]}

One thing that occurred to me, and this from a place of ignorance about the way in which JH's node.js web interface works, as he changes pages from one control surface to another, it is possible (likely?) that the client will retain the web socket connection, but need to register for a new set of VINTs (and possible un-register other VINTs) While there would be nothing wrong with keeping them registered, we would simply send values it had no place to display, at present there is no mechanism yet in place to unregister VINTs within a given session. A couple of options lay before me:
  • Implement an UnregisterVUIDs command.
  • Instruct the client to disconnect and re-connect when a new set of VINT subscriptions is required.
  • Do nothing (Keep all registered VINTs in the session and continue to send their updates.

I'll probably go with option #1, but is there any other option I am overlooking? Is there an advantage to going with #2 or #3 that is not apparent?


12
V_Buscom / Re: Crossroads
« on: February 08, 2018, 04:55:57 PM »
Of course, no sooner did I get to creating the first plugin module (Modbus) than I hit a hurdle: The libmodbus library takes care of all it's own communication. One of the first examples it provides reads:

Code: [Select]
modbus_t *ctx;
ctx = modbus_new_tcp("127.0.0.1", 1502);

Thinking about it deeper though, this may not be a problem at all. CLI handling will need to be modified somewhat, but a series of hooks and callback functions ought to modularize this aspect nicely. For example, I could have the base command handler function check to see if we have a module type installed matching the value of arg[0], and pass off cmd processing to that plugin's command parser.

Another problem I encountered is that under the present system the channels run in their own threads, talking to whatever devices are associated with them. If we create a Modbus RTU device, it will not be associated with any channel, and therefore will not have any thread to work in. We have a couple of options then, we could:
  • Make it a plugin option to create a thread for the module, passing control to a module worker function tasked with looking after the communication of all that module's devices.
  • Make an option per device to have a dedicated worker function managing that device's communication, each of which runs in it's own thread.
  • Something else?

I'm leaning towards option #2 personally, since this gives the most flexibility. This way, a device can be put on a communication channel, or it can do it's own thing. Of course, each module could define it's own communication requirements as part of the API. A module for DSC panels may specify that it's devi ... BREAKING THOUGHT We could add a parameter to the channel structure so that it designates what each channel is for. Channels may be unreserved, IE: Are not linked or tied down to any one module (such as they presently are.) They could also be reserved for a specific module type (this would help clarify their purpose / function when listing the channels and would also prevent the user from inadvertently placing devices from two or more different modules on the same channel. We now return you to your previously scheduled programming thoughts... Back to the DSC panel example, we could create a Plugin for DSC panels. (Maxsys, Power Series and Neo). This plugin would indicate that it's communication is handled at the channel level, and would provide a function pointer to it's main worker thread, one worker for each channel thread. The panel structures would be shared within the plugin code, but protected from multi-threaded access by rwlocks as we have gotten very good at writing, Thus each worker thread would scan the plugin's array of devices, acting only on devices registered for communication on that specific channel.

That approach would then be complimented by the modbus mode, whereby the plugin's devices do not need to associate with any channels on their own (maybe we could even prohibit this (or at least ensure it does not become and option for selection) and enabling a modbus plugin device would create a new thread specifically for handling that device. I think this makes sense, it's becoming clear in my mind -- now to try to implement it!

13
V_Buscom / Crossroads
« on: February 08, 2018, 11:06:52 AM »
Now it comes to that time. Decision time. A Fork In The Road. Buscom appears to be working nicely, and is nearing the point where I would be cloning it into a new project to begin implementing the Mosbus connectivity. But herein lies the crossroad: Is there any benefit to making that an external module versus just incorporating the modbus functionality into buscom? Obviously it need not be utilized if not needed, but what reasons could be contrived to have them separate? Perhaps there is an argument to be made here for using the codebase as it is as a plug-in host for all manner of device-specific processing, since all the other code largely remains the same. I'm thinking of revitalizing the DSC integration module, but again - it would essentially be based on buscom with all it's established code and functionality. I wonder if there might be a way we could standardize on the buscom code and somehow create "plug-in" modules that interact with specific hardware, building on what we've already created. This would simplify the maintenance of code, bugfixes and enhancements to the core would need to be applied to each and every module. What does a modularized system even look like? I've never built "kernel modules" (well, built - yes. Designed / coded: no.) We'd need some demarcation point, probably after the channel had been connected, to turn processing control within each thread over to a function within the module space for "doing something" with that connection, whether that be querying one or more devices, listening for data, or what have you. The module space code would need to be able to allocate it's own memory and Venturii Value Interpreters, generate it's own events, etc. Perhaps this may even be a good place to introduce Lua to the mix, and code the module-specific stuff in Lua script (if that's even what you call it.)

Within the Modbus module, for example, there are dozens of registers, each one holding 16 bits of data. My plan was to create the modbus module such that when you created a channel, you would then add a device (similar to the vdac system) and tell that module how many registers to allocate and the starting address within the PLC. This would then create n * sizeof(register) Value Interpreters (since for us to be able to do things intelligently within Venturii, we pretty much need access to each individual register as a separate entity that can be read and written to independently of all the others. While not the most efficient use of space, (multiplying storage by at least a factor of 8) the functionality requirement outweighs the "waste of bits". But then from there, we haven't much to do. Read all the registers, set the values of each register if any of our VINTs have dvals set, and sleep between poll cycles. The module code would retain control until or unless an error condition occurred by which it became apparent (or desirable / necessary) that the underlying channel connection be reconnected. The module space code need only return (or maybe call some "disconnect()" function and then return) to pass control of the thread back to the buscom code base, which would try to re-establish the connection.

Hmm, the more I think of it, the more I like this paradigm. In fact, i can see all the Venturii modules unifying under this architecture, which would simplify a LOT of code, partially by actually removing most of it, and then only incorporating the device or hardware-specific code itself within these modules. You could even have a single Venturii module talking to many different device types, all within the same process. Arguments could be made on both sides of the table for or against this approach from a single-point-of-failure, redundancy, division of labour or many other basket-to-egg-ratio perspectives, but having the option to hold all the eggs would not mean you couldn't then run multiple "baskets", even having a separate basket for each egg.

This is why I love writing these things down and working them out in text; great ideas form this way and I'm sure down the road it may even be interesting to have a record of the thought process as it formulated within my mind! Haha  The inner workings of my brain on display. Viva Venturii!

14
General Discussion / Snow Day!
« on: February 08, 2018, 08:23:49 AM »
I climbed up on the roof of my garage a few days ago to clear off the snow from my solar panel, only to wake up this morning to another 25 cm of snow sitting on the roof. The entire solar panel is buried so that you cannot even make out where it lays on the roof! Everyone is staying home today. It is remarkable how much snow can accumulate!

One of my favorite sounds on a frigid day like this is the gentle Ahhhh of heated air rising through the vents in the floor, warming the house. Venturii calculates the difference in temperature between the inside air and outside air, and adds more heat inside when it gets colder outside to compensate for the accelerated heat loss through windows, walls and ceiling. I've been wondering and doing a bit of research on applying hot water lines to the underside of the floor sheathing - particularly beneath the stone tiles that lay inside our front, and back doors and main floor bathroom that always feel cool to the foot. Even if we could raise their temperature by a few degrees, it would go far to take the edge off. In my mind a simple recirculating pump and a couple of zone valves could control the flow of hot water from the hot water tank, out through the heating loops and back into the tank. I'm not sure if there would be any issues with doing this with shared domestic hot water, but I guess that's where further research comes into play. Ideally I'd like to do one zone for the front entrance, one for the main floor washroom, one for the kitchen / dining room and one for the back entrance, though it may be more difficult to get lines under the back entrance since part of the basement beneath it is finished. Eventually when we finish the rest of the basement, we'll probably (most likely) do some sort of in-floor heating. I've been in basements where this is the case and it's funny - the effect is so subtle you don't even notice it until you step into the furnace room or some part of the basement without in-floor heating you are suddenly (and startlingly) aware of the difference. For that project, I may even consider electric in-floor heating, thought I am loth to use electricity for heating anything but my tea since it is the most expensive form of heat available here, despite the convenience and ease of precise control.

15
V_Buscom / Buscom - The New Mod Shell
« on: February 05, 2018, 03:55:38 PM »
Years ago I started creating a Venturii module coined Modshell that was designed to be a generic code base from which to easily whip up new modules as I encountered additional systems to integrate Verturii with. Modshell has trailed behind the leading edge of development, though it's concept has recently been revitalized by the development of Buscom. Among other things, Buscom essentially accomplishes one of the same goals Modshell was supposed to.

Buscom is a generic Venturii module. Unlike every other Venturii module which was created to interface with a specific system or piece of hardware, Buscom has been designed to interface with interfaces, not devices. What that means is that Buscom includes all of the code necessary to set up the following connection types:
  • TCP Server (Remote device connects to a listening TCP socket served by Buscom)
  • TCP Client (Buscom connects to a listening TCP socket served by some external host
  • UDP Server (Remote device connects to a listening UDP socket served by Buscom)
  • UDP Client (Buscom connects to a listening UDP socket served by some external host
  • Serial Port (Buscom connects to an external device over a native (16550 or similar based UART) or USB-based Serial Port
  • (Unix) Named Pipe (Buscom connects to another service running on the same host that can communicate over a named pipe

Having established a connection to one or more of these connection types, data can be sent directly to and from that device through Decider. One of the first simple uses I had in mind for this was to set up a dot matrix printer that recorded a log of sorts, printing one line at a time as it was received from Decider. All Decider needs to do is generate a string of text and send it to the appropriate channel on the corresponding Buscom module, and that string will be delivered verbatim to that printer. This, as it turns out, has many other practical uses as well. It turns out that many systems utilize a simple yet powerful system for providing API's to their inner workings. This will actually be the basis for both the Pelco Endura integration and the Harding DXL Intercom System integration, both of which use simple, low level serial protocols for allowing external control of their workings.

Today I have begun returning my focus on Buscom, with the plan being to clean up it's code, run it through a series of tests (including both functional and performance & memory usage - IE: Valgrind) before I begin to fork this project and create a new one, the first child of Buscom, which will be a Modbus module for talking to RTU devices using the protocol already named.

Pages: [1] 2 3 ... 6