Ruby Gem to Read EKM Omnimeter Pulse v.4

For more advanced meter data users. Learn from others and ask questions about how to read meters, how to use the EKM Push Data, and how to display the meter data in useful ways.
jwtd
Posts: 7
Joined: Wed Apr 02, 2014 6:33 pm

Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by jwtd »

I've created a ruby gem that provides an interface to EKM Omnimeter Pulse v.4 meters that are connected to a EKM iSerial TCP/IP Ethernet to RS-485 Serial Converter. Still very early stage, so use at your own risk. Need to write more specs, format some of the response values better, and figure out the correct parsing for a few of the attributes. Hoping this board can help me in that respect.

Source and example usage can be found on the git repo page:
https://github.com/jwtd/ekm-omnimeter

Feedback and bugs can be logged here:
https://github.com/jwtd/ekm-omnimeter/issues

Jordan
Last edited by jwtd on Thu Apr 03, 2014 8:29 pm, edited 2 times in total.
Jameson
Posts: 862
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by Jameson »

HaHa! This is neat :P

Thanks jwtd for posting to our forum and to github.

I see that you mention an issue with the time your meter is reporting, do you know that you can set the meter time? We normally would do this with the EKM Dash software.

Also I see that you have a xively connection. Will you let us know when you get that working?

It looks like your formatting is good from here. Just be aware that if m.kwh_data_decimal_places # 1 it would mean that all kWh values have 1 decimal place.

How you have parsed Max Demand looks like it may be high: 226400

Hey, and thanks for the "awesome hardware" shout out.
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371
jwtd
Posts: 7
Joined: Wed Apr 02, 2014 6:33 pm

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by jwtd »

You're welcome.

Regarding the date, I did set the date via the EKM Dash Software first. Is there a place where you set daylight savings time or timezone? If not, is the time supposed to be UTC?

As for the precision of the kwh readings, I created a method to cast all the kwh attributes to the precision returned by kwh_data_decimal_places. That method is here...

https://github.com/jwtd/ekm-omnimeter/b ... er.rb#L175

...and the list of attributes that get cast to that precision is here...

https://github.com/jwtd/ekm-omnimeter/b ... er.rb#L238

Thanks for pointing out the incorrect precision on Max Demand. Just fixed it.

I haven't figured out how to map the bytes for meter_type or meter_firmware to human readable values yet. I'm getting back a carriage return and a dollar sign. Here is where I'm parsing them out...

https://github.com/jwtd/ekm-omnimeter/b ... er.rb#L290

From the request_a spec, I was able to pull "pulse_input_hilo", but I can't figure out how that maps to pulse_input_1, pulse_input_2, or pulse_input_3 values that I see in the EKM Dash. Same goes for "direction_of_current". I can't figure out how to get current_direction_L1, current_direction_L2, current_direction_L3 from it. And same goes for "outputs_onoff". I can't figure out how to get output_1 or output_2. Do those come from other calls? If so, could you point me to the correct line in the spec? Thanks!
jwtd
Posts: 7
Joined: Wed Apr 02, 2014 6:33 pm

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by jwtd »

I found the value maps for pulse input state, current direction, output state, demand period time, and auto reset max demand in the parsing reference PDF. The only two maps I haven't found yet are the Firmware and Meter Type lookup maps.
Jameson
Posts: 862
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by Jameson »

Hello jwtd,

Here is the PDF you are referring to (for others that read this), the values you are referring to are in green lettering: http://documents.ekmmetering.com/Omnime ... arsing.pdf

Here is the entire list of communicating meters, some of these are discontinued.

Model number bytes:
10 11 15IDS-N
10 12 25IDS-N
10 13 23EDS-N
10 14 15EDS-N
10 15 25EDS-N
10 16 23EDS-N
10 18 5A25EDS-N
10 20 25EDSP-N
***
OmniMeter I v.3 10 17 fw 13 or 14
OmniMeter II UL v.3 10 22 fw 14
OmniMeter Pulse v.4 10 24 fw 15 or 16
Regarding the date, I did set the date via the EKM Dash Software first. Is there a place where you set daylight savings time or timezone? If not, is the time supposed to be UTC?
Yes, the Dash was screwy how it interpreted time. We have fixed this now in our latest development version and the new way will be included with the next release of the Dash.

Thanks,
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371
jwtd
Posts: 7
Joined: Wed Apr 02, 2014 6:33 pm

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by jwtd »

Thanks for getting back to me on the models.

In the spec, it says the meter_type us 2 Bytes and the firmware version is 1 Byte. Let me make sure I understand how to interpret the table you provided.

If model number bytes are a "10" and "11", the model is a "15IDS-N". Is that correct? So for the communicating meters, a "10" and "24", the model is a "OmniMeter Pulse v.4", correct?

And to confirm, the firmware byte is just the 13, 14, 15, or 16, correct?

Thanks again,

Jordan
jwtd
Posts: 7
Joined: Wed Apr 02, 2014 6:33 pm

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by jwtd »

No need to reply, I got it working.

the_bytes.unpack('H*') gave me the correct combination of values.

"\x10$".unpack('H*') -> ["1024"]
"\x15".unpack('H*') -> ["15"]

Thanks!
jwtd
Posts: 7
Joined: Wed Apr 02, 2014 6:33 pm

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by jwtd »

I'm having trouble getting the CRC check to match. I tried to implement the algorithm described here http://forum.ekmmetering.com/viewtopic.php?f=4&t=5#p557

My implementation is here...

https://github.com/jwtd/ekm-omnimeter/b ... r/crc16.rb

Response from snippet (2nd byte through third from last byte, inclusive):
\x10$\x1500030000023400311088001820740000000000000000000047930000279700000000000000001250124700000022800288000000002848000360800000000006456 100 100C000002264001100000031000040000800000000000000000000000000000000000000000000000000000000001404080300101801!\r\n\x03

Expected CRC Value: "x\x7F" -> "787f"

Response snippet using ruby's s.bytes method
[16, 36, 21, 48, 48, 48, 51, 48, 48, 48, 48, 48, 50, 51, 52, 48, 48, 51, 49, 49, 48, 56, 56, 48, 48, 49, 56, 50, 48, 55, 52, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 52, 55, 57, 51, 48, 48, 48, 48, 50, 55, 57, 55, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 50, 53, 48, 49, 50, 52, 55, 48, 48, 48, 48, 48, 48, 50, 50, 56, 48, 48, 50, 56, 56, 48, 48, 48, 48, 48, 48, 48, 48, 50, 56, 52, 56, 48, 48, 48, 51, 54, 48, 56, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 54, 52, 53, 54, 32, 49, 48, 48, 32, 49, 48, 48, 67, 48, 48, 48, 48, 48, 50, 50, 54, 52, 48, 48, 49, 49, 48, 48, 48, 48, 48, 48, 51, 49, 48, 48, 48, 48, 52, 48, 48, 48, 48, 56, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 52, 48, 52, 48, 56, 48, 51, 48, 48, 49, 48, 49, 56, 48, 49, 33, 13, 10, 3]

Running these bytes through the normal CRC algo, I get 38708
I'm using a little indian processor, so I didn't reverse the bytes.
Masking the CRC per the thread, I get 13335, which does not match the last two bytes.

One thing I noticed in that thread I linked to above is that the bytes from the sample response look more like this...

Response snippet by unpacking string as hex bytes s.split().map{ |i| i.unpack('H*')[0]}
["10", "24", "15", "30", "30", "30", "33", "30", "30", "30", "30", "30", "32", "33", "34", "30", "30", "33", "31", "31", "30", "38", "38", "30", "30", "31", "38", "32", "30", "37", "34", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "34", "37", "39", "33", "30", "30", "30", "30", "32", "37", "39", "37", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "31", "32", "35", "30", "31", "32", "34", "37", "30", "30", "30", "30", "30", "30", "32", "32", "38", "30", "30", "32", "38", "38", "30", "30", "30", "30", "30", "30", "30", "30", "32", "38", "34", "38", "30", "30", "30", "33", "36", "30", "38", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "36", "34", "35", "36", "20", "31", "30", "30", "20", "31", "30", "30", "43", "30", "30", "30", "30", "30", "32", "32", "36", "34", "30", "30", "31", "31", "30", "30", "30", "30", "30", "30", "33", "31", "30", "30", "30", "30", "34", "30", "30", "30", "30", "38", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "31", "34", "30", "34", "30", "38", "30", "33", "30", "30", "31", "30", "31", "38", "30", "31", "21", "0d", "0a", "03"]

I'm thinking maybe I have the byte unpacking incorrect???
Jameson
Posts: 862
Joined: Fri Nov 04, 2011 7:42 pm
Location: Santa Cruz, CA
Contact:

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by Jameson »

Hello Jordan,

Yes, the first thing I would look at is how you are getting bytes that start with a 4, a 5, or a 6.

Our meter responds with 99% of the Hex bytes are "3x". So 30,31,32, etc. 30 in Hex equals 0 in ASCII, 31 in Hex equals 1 in ASCII, etc.

Are you sure that you are using the correct serial settings? 7 data bits, even parity, 1 stop bit, and no hardware flow control.
\x10$\x1500030000023400311088001820740000000000000000000047930000279700000000000000001250124700000022800288000000002848000360800000000006456 100 100C000002264001100000031000040000800000000000000000000000000000000000000000000000000000000001404080300101801!\r\n\x03
This looks like an ASCII response.

Hope this helps.
Jameson
EKM METERING
http://www.ekmmetering.com
831.425.7371
jwtd
Posts: 7
Joined: Wed Apr 02, 2014 6:33 pm

Re: Ruby Gem to Read EKM Omnimeter Pulse v.4

Post by jwtd »

I have the meter hooked up as a remote meter using an iSerial converter. I'm getting the data back using Ruby's native TCPSocket lib, which gives me generic read and write methods. The code for the call is here https://github.com/jwtd/ekm-omnimeter/b ... er.rb#L388. I assumed that since the response from the meter is parsing out to all the correct values, the read/write calls were correct. I logged into my iSerial web dashboard and reviewed the UART Control screen. Values are as follows:

Mode: RS485
Baudrate: 9600
Character Bits: 7
Parity Type: even
Stop Bit: 1
Hardware Flow Control: none
Uart Memory: 0M, 0k, 0Byte
Uart FIFO Overflow count: 0times
No delimiters

So the response from the iSerial device arrives as that ASCII string. If I unpack it to Hex like so...

s.split().map{ |i| i.unpack('H*')[0]}

I get an array of string which seem to hold the correct hex byte values. Problem is, they aren't bytes, they're strings. This is probably just a ruby type conversion puzel I have to work out.

["10", "24", "15", "30", "30", "30", "33", "30", "30", "30", "30", "30", "32", "33", "34", "30", "30", "33", "31", "31", "30", "38", "38", "30", "30", "31", "38", "32", "30", "37", "34", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "34", "37", "39", "33", "30", "30", "30", "30", "32", "37", "39", "37", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "31", "32", "35", "30", "31", "32", "34", "37", "30", "30", "30", "30", "30", "30", "32", "32", "38", "30", "30", "32", "38", "38", "30", "30", "30", "30", "30", "30", "30", "30", "32", "38", "34", "38", "30", "30", "30", "33", "36", "30", "38", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "36", "34", "35", "36", "20", "31", "30", "30", "20", "31", "30", "30", "43", "30", "30", "30", "30", "30", "32", "32", "36", "34", "30", "30", "31", "31", "30", "30", "30", "30", "30", "30", "33", "31", "30", "30", "30", "30", "34", "30", "30", "30", "30", "38", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "30", "31", "34", "30", "34", "30", "38", "30", "33", "30", "30", "31", "30", "31", "38", "30", "31", "21", "0d", "0a", "03"]
Post Reply