@Yveaux said:
I think we could drop the protocol version number and use a full byte for command type.
When, in the future, a command gets extended we can just reserve a new command-number for it. All existing applications will only recognize the old command-number and ignore the new one. As @zeph already pointed out this allows for more efficient usage of the 8 bits and a new version will not immediately disqualify an onld node completely as it will stil listen & respond to old commands.
The value of having defined groups of command associated with a given protocol version is that you can get a pretty good idea of what a node will understand (or send). The first approach was to have some fixed number of bits for a protocol id, and some number for command-within-protocol (like 8+8 or 5+3 or whatever). I'm glad you see the advantages of adding command codes sequentially instead, especially if we are using one byte.
I was suggesting that a given protocol version define a contiguous range of commands (plus some universal ones at the beginning of the codes). One caveat was that the "current protocol version" would be allowed to add new commands at the end of the sequence - the "last command allowed in this version" doesn't get frozen until a version is superceded by another one. Any given node need only understand the universal commands plus the range corresponding to the protocol version it was written to. So each version has the common universal commands plus a non-overlapping range of command specific to this version.
The disadvantage is that you may have to redefine new command codes for commonly needed commands like "set value" every time you move to the next version. So in the first version, command 4 might be set (part of range 3..9). Then in the next version with commands (10..17) we have to define a new "set value" within that range, maybe code 11. Nodes implementing the second version only understand commands 0..2 (universal) and 10..17, they have no need to understand version one commands 3..9. A gateway would not expect a version 2 node to understand command 6. The hub could ask the node for the start and end of the range of commands it can accept.
===
One variant, which you are suggesting I think, is to ignore versoin based commadn code sub-ranges and just keep all commands allowable to all nodes. This has the advantage that "Set value" command 4 (in the above example) can continue to be used "forever", and not need to be reallocated code 11 to fit within the new version's range.
But it may over time cause fragmentation or bloat - either we carry around the code to handle all commands (eg: 1.3 and 1.4 both), or the set of commands allowed once you switch to a new protocol version is non-contiguous (it contains some but not all commands from the older protocol version). I actually considered this, and the possibility of having the node respond to "what commands can you handle" with a bitmap instead of a start and end value, but decided that was getting too complicated. That was just my judgement call tho.
(If you can correctly anticpate this kind of command in the "universal commands" that are part of all versions, the issue goes away. In the first appraoch, maybe "set value" is command 2 and globally available, not needing to be allocated a code in each versions's code range) But sometimes your concept changes more than you anticipated and "set value" might need to become a new command type in newer protocols).
Deciding among these options depends somewhat on one's philosophy of where configuration information should be stored - in the nodes or in the hub. There are many answers to this question at different granularities. If you accept the concept of storing much config on the hub, then another approach emerges:
each node can use a basic common protocol to report on first connecting what version of the full protocol it implements
that per-node protocol version is stored in the hub
the hub has bitmaps or tables of what command codes work for each protocol version it understands
if the hub understands more than one version, it can communicate with nodes using any of those versions
In this case, you don't make every packet include an explicit (fixed bits allocated) or implicit (code range) protocol version. But the hub could still know which commands work and don't work for any given node.