-
Notifications
You must be signed in to change notification settings - Fork 0
/
senml_parser.rb
90 lines (71 loc) · 2.11 KB
/
senml_parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
require 'cbor'
require 'date'
require 'json'
SenMLParseException = Class.new(Exception)
##
# Representation of a sensor measurement
class SensorReading
attr_accessor :name, :time, :value, :unit
end
##
# see http://tools.ietf.org/html/draft-jennings-senml-10
# not implemented yet: version, sum and update time
class SenMLParser
##
# parses simple hash
# returns array of SensorReading objects
def self.parse(obj_data)
readings = []
base_name , base_unit, base_time, elements =
parse_base_elements(obj_data)
elements.each do |item|
readings << generate_sensor_reading(item, base_name,
base_unit, base_time)
end
readings
end
##
# parses application/senml+json
# returns array of SensorReading objects
def self.parse_json(json_string)
json_object = parse_json_string(json_string)
parse(json_object)
end
##
# parses application/senml+cbor
# returns array of SensorReading objects
def self.parse_cbor(bin_data)
object_data = CBOR.decode(bin_data)
parse(object_data)
end
private
def self.parse_json_string(json_string)
begin
json_object = JSON.parse(json_string)
rescue
raise SenMLParseException, 'Unable to parse JSON'
end
json_object
end
def self.parse_base_elements(obj)
base_name = obj['bn'] || ''
base_unit = obj['bu'] || ''
# if there is no specification of time, it is assumed the reading
# occured right now
base_time = DateTime.now
base_time = DateTime.strptime(obj['bt'].to_s, '%s')\
if obj['bt']
fail SenMLParseException,
'No sensor readings found' unless obj['e']
[base_name, base_unit, base_time, obj['e']]
end
def self.generate_sensor_reading(item, base_name, base_unit, base_time)
new_reading = SensorReading.new
new_reading.name = base_name + (item['n'] || '')
new_reading.value = item['v'] || item['sv'] || item['bv']
new_reading.unit = item['u'] || base_unit
time_offset_seconds = item['t'] || 0
new_reading.time = base_time + Rational(time_offset_seconds, 86_400)
new_reading
end
end