[UPDATED] node-red-contrib-buffer-parser - V3.1.2

It should be noted for non-industrial people who frequent this forum. While standards do exist in how companies should structure a communication protocol between a master/slave or server/client, not all manufactures follow it. In some cases, not in the least bit. Modbus is a prime example as its implementation is used by so many manufacturers.

More often than not, you find yourself polling an address range just to see if something comes back that you can make sense of.

Therefore the node must be extremely flexible/universal in whatever scenario it may be used in. Having ability to swap multiple times could be a life saver for someone out there, if not a necessity.

2 Likes

here here! many a time :slight_smile:

Update V2.0.2 now available.

Some bugs squished and some UI tweaks implemented as kindly suggested by @cymplecy & @dceejay

Q. Should UI tweaks be a 0.x.0 minor version bump or a 0.0.x patch version bump? :thinking:

1 Like

If they expose new capability then minor - if just fixes, clarifications, corrections then a patch.

1 Like

Updated to V2.4.0

change since last posting here

Functionality ...

  • add key.value output option
    • this improves usability by presenting the data as an object with key / values
  • allow item type to be buffer
    • this permits you so split a buffer into multiple buffers
  • add scaling option (a simple multiplier)
    • this permits an item value to be changed before output e.g. often values are stored in a PLC as integer but really represent a float value. e.g. data value might be 3623 but actual real value should be 36.23, applying a multiplier of 0.01 will return the value you need

UI ...

  • when adding a new item to the list, auto copy the selected type from last item to newly added item
  • auto increment newly added items offset based on prev length and type

Bugs...

  • when a string is passed in, it should be interpreted as a HEX string (e.g. A1EF44FEFF1B) - this was not the case. Now fixed in 2.4.0

cheers.

2 Likes

Could you please add "hex" to string output type. It will be useful for text representation of ids.

One more idea, to have an ability to return the rest of the buffer for the last item.
I can achieve it with specification, but it will be simpler with UI

Seems reasonable.

Not certain how I can achieve that - perhaps if the last items length was -1 it could signify "to the end". Hmmm. Will think on it.

HOWEVER, would you please raise these on the issue tracker so that they dont get forgotten (a simple title and link to this thread should suffice)

Raised issues, thanks

Good idea, or just if length is empty

Hi @mikeS7, both requests are now complete and published as V2.5.1

Thanks very much for the PR but unfortunately, you must have pushed that as I was writing the code :open_mouth:

V2.5.1 - whats new...

  • can now return hex string items (e.g. specifying an entry with "hex" type will return values like "7b1abbef4522ff")
  • can now set length to -1 to return remainder of data
    • this works for all data types
    • e.g. if type is buffer and byte offset==16 is length==-1 and input data is 20 bytes long, you will get the remaining 4 bytes in a buffer
    • e.g. if type is int16 and byte offset==16 is length==-1 and input data is 20 bytes long, you will get the remaining 4 bytes as 2 integers
1 Like

Thanks a lot!
About PR, I need to complete the functionality before BBQ time :stuck_out_tongue_winking_eye:
you said that you need time to think about

PS I'm thinking about length encoded and symbol terminated for strings, arrays and buffers but don't have an idea about the interface

I did & again my apologies - next time, gimmie a heads up.

Working with Modbus data using Buffer parser

  1. Can I use Uint32(be) and biguint64(be) in same buffer parser with multiple outputs enabled.

Buffer-parsers for different parameters

  • Uint32(be) - Output property - msg.payload , Output - Key/value

  • biguint64(be) - Output property - bigvalues , Output - Key/object

If I use Uint32(be) and biguint64(be) together with output property as msg.payload and output as key/value - for **biguint64(be) **parameters , I'm getting NAN error

  1. Whether Buffer-parser will work with Offset 300 ?
    (while working Offset 200 , I can get the output of Modbus data, While trying with Offset 300 no output

  2. Any possible way to do Scale for biguint64(be) parameters

Appreciate , if some one help me in resolving it

thank you !

Energy Charges

Yes - same as you can have bytes, ints UINTs 16bit/32bit whatever you want.

can you copy a FULL msg debug value (using the "copy value" button that appears under your mouse when you hover over the debug message) of data going INTO the buffer parser then

  • paste the full debug message into a reply formatted as code (between ``` backticks)
  • paste an export of the buffer parser (select the buffer parser, press CTRL+E, then copy) into a reply formatted as code (between ``` backticks)

If there are 300+ bytes going in - yes
NOTE: You will probably crash node-red accessing more than 200 bytes using modbus tcp (something I have witnessed and commented on before)

Yes, but not in buffer parser (yet) - you can simply add a function node after the buffer parser and perform the math required.

  1. Yes - same as you can have bytes, ints UINTs 16bit/32bit whatever you want.
    Yeah , i tried for 16bit/32bit, but my question is whether it works for biguint64(be) . i tried with Uint32(be) & biguint64(be ) output property - msg.payload and output as key/value
    i got error for biguint64 as NAN

  2. paste the full debug message into a reply formatted as code (between ````` backticks)

[{"id":"39389276.d99bfe","type":"inject","z":"8ace6ce4.5870f","name":"ENERGY_Test","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"300","crontab":"","once":false,"onceDelay":"10","topic":"","payload":"","payloadType":"date","x":160,"y":180,"wires":[["c9bf96ed.801f28","6435d039.e9a9a","7827f28b.08cf5c","2f67b1c0.9232ee","3fab6935.0ffff6"]]},{"id":"c9bf96ed.801f28","type":"function","z":"8ace6ce4.5870f","name":"address:0","func":"msg.payload ={\n    'fc':3,\n    'unitid':1,\n    'address':0,\n    'quantity':24\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":360,"y":100,"wires":[["617bb675.945568"]]},{"id":"2f67b1c0.9232ee","type":"function","z":"8ace6ce4.5870f","name":"address:80","func":"msg.payload ={\n    'fc':3,\n    'unitid':1,\n    'address':80,\n    'quantity':50\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":390,"y":180,"wires":[["53c48d6a.e5ee24"]]},{"id":"53c48d6a.e5ee24","type":"modbus-flex-getter","z":"8ace6ce4.5870f","name":"Modbus","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"84124d7e.073d7","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":540,"y":180,"wires":[["b824dca1.d8def"],[]]},{"id":"3fab6935.0ffff6","type":"function","z":"8ace6ce4.5870f","name":"address:1024","func":"msg.payload ={\n     value: msg.payload,\n    'fc':3,\n    'unitid':1,\n    'address':1024,\n    'quantity':36\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":380,"y":260,"wires":[["d747403d.71168"]]},{"id":"d747403d.71168","type":"modbus-flex-getter","z":"8ace6ce4.5870f","name":"Modbus","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"84124d7e.073d7","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":540,"y":260,"wires":[["c0b7df5f.e830d"],[]]},{"id":"b824dca1.d8def","type":"buffer-parser","z":"8ace6ce4.5870f","name":"DPF/TAN/THDV/THD","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"int32be","name":"DPF1","offset":0,"length":1,"offsetbit":0,"mask":""},{"type":"int32be","name":"DPF2","offset":4,"length":1,"offsetbit":0,"mask":""},{"type":"int32be","name":"DPF3","offset":8,"length":1,"offsetbit":0,"mask":""},{"type":"int32be","name":"TAN1","offset":12,"length":1,"offsetbit":0,"mask":""},{"type":"int32be","name":"TAN2","offset":16,"length":1,"offsetbit":0,"mask":""},{"type":"int32be","name":"TAN3","offset":20,"length":1,"offsetbit":0,"mask":""},{"type":"int32be","name":"TANSys","offset":24,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDV1","offset":28,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDV2","offset":32,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDV3","offset":36,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDV12","offset":40,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDV23","offset":44,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDV31","offset":48,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDA1","offset":52,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDA2","offset":56,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDA3","offset":60,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"THDAN","offset":64,"length":1,"offsetbit":0,"mask":""},{"type":"uint32be","name":"Freq","offset":68,"length":1,"offsetbit":0,"mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"output","multipleResult":false,"setTopic":true,"x":720,"y":180,"wires":[["9484b6e8.42c078"]]},{"id":"c0b7df5f.e830d","type":"buffer-parser","z":"8ace6ce4.5870f","name":"Energy","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"bigint64be","name":"KWH_1i","offset":0,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_1e","offset":8,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_2i","offset":16,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_2e","offset":24,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_3i","offset":32,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_3e","offset":40,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_Sysi","offset":48,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_Syse","offset":56,"length":1,"offsetbit":0,"mask":""},{"type":"bigint64be","name":"KWH_BAL","offset":64,"length":1,"offsetbit":0,"mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"bigValues","msgPropertyType":"str","resultType":"object","resultTypeType":"output","multipleResult":false,"setTopic":true,"x":680,"y":260,"wires":[["93e621ee.5566"]]},{"id":"6435d039.e9a9a","type":"function","z":"8ace6ce4.5870f","name":"address:24","func":"msg.payload ={\n     value: msg.payload,\n    'fc':3,\n    'unitid':1,\n    'address':24,\n    'quantity': 48\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":370,"y":220,"wires":[["a4811bce.1399b8"]]},{"id":"119bf36b.21c0ad","type":"function","z":"8ace6ce4.5870f","name":"ReadInt 64","func":"   msg.payload = {\n   \n   P1 : Number(msg.bigValues.P1.value),\n   P2 : Number(msg.bigValues.P2.value),\n   P3 : Number(msg.bigValues.P3.value),\n   Psys : Number(msg.bigValues.Psys.value), \n   S1 : Number(msg.bigValues.S1.value),\n   S2 : Number(msg.bigValues.S2.value),  \n   S3 : Number(msg.bigValues.S3.value),\n   Ssys : Number(msg.bigValues.Ssys.value),\n   Q1 : Number(msg.bigValues.Q1.value),\n   Q2 : Number(msg.bigValues.Q2.value),  \n   Q3 : Number(msg.bigValues.Q3.value),\n   Qsys : Number(msg.bigValues.Qsys.value),\n   }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":790,"y":220,"wires":[["9484b6e8.42c078"]]},{"id":"74894602.da35b8","type":"buffer-parser","z":"8ace6ce4.5870f","name":"P/S/Q","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"biguint64be","name":"P1","offset":0,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"biguint64be","name":"P2","offset":8,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"biguint64be","name":"P3","offset":16,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"biguint64be","name":"Psys","offset":24,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"biguint64be","name":"S1","offset":32,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"biguint64be","name":"S2","offset":40,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"biguint64be","name":"S3","offset":48,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"bigint64be","name":"Ssys","offset":56,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"bigint64be","name":"Q1","offset":64,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"bigint64be","name":"Q2","offset":72,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"bigint64be","name":"Q3","offset":80,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"bigint64be","name":"Qsys","offset":88,"length":1,"offsetbit":0,"scale":1,"mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"bigValues","msgPropertyType":"str","resultType":"object","resultTypeType":"output","multipleResult":false,"setTopic":true,"x":650,"y":220,"wires":[["119bf36b.21c0ad"]]},{"id":"93e621ee.5566","type":"function","z":"8ace6ce4.5870f","name":"ReadInt 64","func":"   msg.payload = \n   {\n\nKWH_1i : Number(msg.bigValues.KWH_1i.value),\nKWH_1e : Number(msg.bigValues.KWH_1e.value),\nKWH_2i : Number(msg.bigValues.KWH_2i.value),\nKWH_2e : Number(msg.bigValues.KWH_2e.value), \nKWH_3i : Number(msg.bigValues.KWH_3i.value),\nKWH_3e : Number(msg.bigValues.KWH_3e.value),\nKWH_Sysi : Number(msg.bigValues.KWH_Sysi.value),\nKWH_Syse : Number(msg.bigValues.KWH_Syse.value), \nKWH_BAL : Number(msg.bigValues.KWH_BAL.value),\n\n   }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":830,"y":260,"wires":[["9484b6e8.42c078"]]},{"id":"9484b6e8.42c078","type":"join","z":"8ace6ce4.5870f","name":"","mode":"custom","build":"merged","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"7","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":850,"y":120,"wires":[["4656a476.aad35c"]]},{"id":"a9e3215d.59886","type":"buffer-parser","z":"8ace6ce4.5870f","name":"PF","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"int32be","name":"PF1","offset":0,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"int32be","name":"PF2","offset":4,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"int32be","name":"PF3","offset":8,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"int32be","name":"PFsys","offset":12,"length":1,"offsetbit":0,"scale":1,"mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"output","multipleResult":false,"setTopic":true,"x":670,"y":140,"wires":[["9484b6e8.42c078"]]},{"id":"7827f28b.08cf5c","type":"function","z":"8ace6ce4.5870f","name":"address:72","func":"msg.payload ={\n    'fc':3,\n    'unitid':1,\n    'address':72,\n    'quantity':20\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":370,"y":140,"wires":[["9226d2b0.2614b"]]},{"id":"232681e6.a14f0e","type":"buffer-parser","z":"8ace6ce4.5870f","name":"Voltage","data":"payload","dataType":"msg","specification":"spec","specificationType":"ui","items":[{"type":"uint32be","name":"V1","offset":0,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"V2","offset":4,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"V3","offset":8,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"V12","offset":12,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"V23","offset":16,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"V31","offset":20,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"Vsys","offset":24,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"A1","offset":28,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"A2","offset":32,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"A3","offset":36,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"AN","offset":40,"length":1,"offsetbit":0,"scale":1,"mask":""},{"type":"uint32be","name":"Asys","offset":44,"length":1,"offsetbit":0,"scale":1,"mask":""}],"swap1":"","swap2":"","swap3":"","swap1Type":"swap","swap2Type":"swap","swap3Type":"swap","msgProperty":"payload","msgPropertyType":"str","resultType":"keyvalue","resultTypeType":"output","multipleResult":false,"setTopic":true,"x":660,"y":100,"wires":[["9484b6e8.42c078"]]},{"id":"617bb675.945568","type":"modbus-flex-getter","z":"8ace6ce4.5870f","name":"Modbus","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"84124d7e.073d7","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":520,"y":100,"wires":[["232681e6.a14f0e"],[]]},{"id":"a4811bce.1399b8","type":"modbus-flex-getter","z":"8ace6ce4.5870f","name":"Modbus","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"84124d7e.073d7","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":520,"y":220,"wires":[["74894602.da35b8"],[]]},{"id":"9226d2b0.2614b","type":"modbus-flex-getter","z":"8ace6ce4.5870f","name":"Modbus","showStatusActivities":false,"showErrors":false,"logIOActivities":false,"server":"84124d7e.073d7","useIOFile":false,"ioFile":"","useIOForPayload":false,"emptyMsgOnFail":false,"keepMsgProperties":false,"x":520,"y":140,"wires":[["a9e3215d.59886"],[]]},{"id":"84124d7e.073d7","type":"modbus-client","z":"","name":"seneca","clienttype":"simpleser","bufferCommands":true,"stateLogEnabled":false,"queueLogEnabled":false,"tcpHost":"192.168.1.9","tcpPort":"502","tcpType":"DEFAULT","serialPort":"/dev/ttyUSB0","serialType":"RTU-BUFFERD","serialBaudrate":"9600","serialDatabits":"8","serialStopbits":"1","serialParity":"none","serialConnectionDelay":"100","unit_id":"1","commandDelay":"1","clientTimeout":"1000","reconnectOnTimeout":true,"reconnectTimeout":"2000","parallelUnitIdsAllowed":true}]
  1. If there are 300+ bytes going in - yes
    NOTE: You will probably crash node-red accessing more than 200 bytes

Any other possibility to use offset 300 , to prevent from crash

  1. Yes, but not in buffer parser (yet) - you can simply add a function node after the buffer parser and perform the math required.

I have used in a separate function node that can perform calculations . to make things simpler under 1 bufferparser , I raised that question

And as I said last time - "Yes - same as you can have bytes, ints UINTs 16bit/32bit whatever you want"

Let me try to be 100% clear. YES YOU CAN HAVE Uint32(be) and biguint64(be) in same buffer parser.

The reason you will be getting NaN is because the input data is probably BAD (or not suitable for converting into BigInt) - that is why I asked for your debug data so I could check why you are getting NaN



You have pasted your full flow AND you HAVE NOT pasted a debug output. You also didnt format the code between 2 sets of 3 backticks.

Again, one more time (hopefully clearer)...

Can you copy a FULL msg debug value (using the "copy value" button that appears under your mouse when you hover over the debug message) of the msg going INTO the buffer parser where this error occurs

e.g.

image

  • paste the full debug message into a reply formatted as code, between three ``` backticks
    ```
    like this
    ```

  • paste an export of the ONE buffer parser (select the ONE buffer parser, press CTRL+E, then copy) into a reply formatted as code, between three ``` backticks
    ```
    like this
    ```

How to export only one node: Select the node, press CTRL+E, then ensure "Selected Nodes" is selected...
image



yes, fix the modbus nodes.

New node added to package : buffer-maker

In a nutshell, its is (almost) the opposite of buffer-parser

this permits you to convert multiple sources of data into a buffer - useful for when preparing data to write to a (for example) a PLC or serial port.

Demonstrating building a buffer from various sources like msg, flow, global, JSONata, constants, etc...

buffer-maker - Summary of functionality

  • Set-up a specification and convert multiple values into a buffer from...
    • int, int8, byte, uint, uint8,
    • int16, int16le, int16be, uint16, uint16le, uint16be,
    • int32, int32le, int32be, uint32, uint32le, uint32be,
    • bigint64, bigint64be, bigint64le, biguint64, biguint64be, biguint64le,
    • float, floatle, floatbe, double, doublele, doublebe,
    • 8bit, 16bit, 16bitle, 16bitbe, bool,
    • bcd, bcdle, bcdbe,
    • string, hex, ascii, utf8, utf16le, ucs2, latin1, binary, buffer
  • Specification is either configured by the built in UI or can be set by a msg/flow/global
  • Input data for each item to include in the final buffer can come from just about anywhere, making it very flexible...
    • a constant (e.g. a number, a string, a boolean, a JSON array)
    • a msg property (e.g from msg.payload.myInteger )
    • a flow property (e.g from flow.myInteger )
    • a global property (e.g from global.myInteger )
  • The final built buffer can be byte swapped one or more times. 16, 32 or 64 bit swaps are possible. The byte swaps are performed the data conversions like LE or BE functions (sometimes it is necessary to do multiple swaps)
  • The final buffer can be output to any msg property (defaults to msg.payload )
  • Built in help
2 Likes

Sneak Peak of Update V3.1.0 (release planned later this evening)

Added new (basic) "Scale Equation" scaling capability to the parser node to greatly improve situations like bit shifting (i.e. multiplying by 0.125 to shift right 4 bits is hardly intuitive :slight_smile: )


image
spot the deliberate error in the descriptions of > and < above

Added New option - fan out


Bugs / tweaks...

  • binary mask (e.g 0b0101) now works
  • octal mask (e.g 0o77) now works

Acknowledgements...
@dceejay for the nudge on all three of these improvement items.

2 Likes

Yikes. I meant single ! To mean twos complement of the value so. !0b101 would become 0b010. Etc. Fine with !! Being an evaluation

I too thought that when I added the operator it but for some reason completely forgot and went on to document it as it functioned haha.

You are 100% right tho because ==0 is the same as single ! so it is redundant.

There's time to revise it later this afternoon.

And I'll happily accept a code snippet on performing the 2s compliment in the meantime to same me figuring how to do that in js. :smiley:

Hmm - now I've said it I'm not sure what I am asking for :-)....
As we are converting to a javascript object I think it will depend on the number of bits in the mask (or the length) - I think the tilde ~ operator does just flip all the bits - but that means all so if I had
0b00111100 and a mask of 0b11110000 and asked for ! then the order of application will matter... as If I mask first and get 00110000 then flip I get 11001111 and if I flip first I get 11000011 then mask I get 11000000 .

I don't want you to have to get into multiple operations just yet... ! >> 4 etc - so maybe just drop / hide ! option for now... also less sure on !! for now... As I said it's easy to add later as and when - harder to change/remove if not quite right but released.

As I said there is the javascript ~ operator which could be used as-is and indeed the ^ xor operator... but again - let's not rush in.

But loving the fan out. I won't mention port labels just yet :wink: