1d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata#!/usr/bin/env python3
2d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata#
3d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# Copyright (C) 2017 The Android Open Source Project
4d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata#
5d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# Licensed under the Apache License, Version 2.0 (the "License");
6d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# you may not use this file except in compliance with the License.
7d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# You may obtain a copy of the License at
8d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata#
9d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata#      http://www.apache.org/licenses/LICENSE-2.0
10d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata#
11d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# Unless required by applicable law or agreed to in writing, software
12d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# distributed under the License is distributed on an "AS IS" BASIS,
13d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# See the License for the specific language governing permissions and
15d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# limitations under the License.
16d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata#
17d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
18d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# OBD2 standard sensor indices are different from those used by the
19d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# Android Auto Diagnostics API. This script maps from OBD2 sensors to
20d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# those expected by the Diagnostics API.
21d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# To use:
22d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# ./obd2_to_diagjson.py --src file1.json --dst file2.json
23d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# It is acceptable and supported to point --src and --dst to the same file
24d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
25d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataimport collections
26d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataimport json
27d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataimport os, os.path, sys
28d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
29d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataclass Json(object):
30d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    @classmethod
31d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def load(cls, file):
32d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return Json(json.load(file))
33d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
34d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    @classmethod
35d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def wrapIfNeeded(cls, item):
36d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        if isinstance(item, list) or isinstance(item, dict):
37d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            return Json(item)
38d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return item
39d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
40d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __init__(self, doc):
41d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.doc = doc
42d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
43d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __str__(self):
44d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return str(self.doc)
45d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
46d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __repr__(self):
47d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.__str__()
48d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
49d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __getattr__(self, attr):
50d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return Json.wrapIfNeeded(self.doc.get(attr))
51d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
52d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __iter__(self):
53d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        class Iter(object):
54d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            def __init__(self, doc):
55d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata                self.doc = doc.__iter__()
56d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
57d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            def __next__(self):
58d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata                return Json.wrapIfNeeded(self.doc.__next__())
59d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
60d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return Iter(self.doc)
61d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
62d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataclass OrderedStore(object):
63d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __init__(self):
64d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.__dict__['store'] = collections.OrderedDict()
65d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
66d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __setattr__(self, name, value):
67d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.__dict__['store'][name] = value
68d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
69d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __getattr__(self, name):
70d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.__dict__['store'][name]
71d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
72d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def get(self, name, default=None):
73d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.__dict__['store'].get(name, default)
74d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
75d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def getStore(self):
76d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.__dict__['store']
77d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
78d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __iter__(self):
79d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return iter(self.__dict__['store'])
80d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
81d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __delattr__(self, name):
82d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        del self.__dict__['store'][name]
83d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
84d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __str__(self):
85d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return str(self.__dict__['store'])
86d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
87d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def toJSON(self):
88d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return json.dumps(self.store)
89d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
90d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataclass Event(object):
91d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def __init__(self):
92d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.store = OrderedStore()
93d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
94d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def setTimestamp(self, timestamp):
95d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.store.timestamp = timestamp
96d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self
97d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
98d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def getTimestamp(self):
99d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.store.timestamp
100d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
101d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def setType(self, type):
102d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.store.type = type
103d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self
104d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
105d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def getType(self):
106d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.store.type
107d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
108d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def setStringValue(self, string):
109d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        if string:
110d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            self.store.stringValue = string
111d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self
112d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
113d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def getStringValue(self):
114d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.store.get('stringValue')
115d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
116d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def setIntValue(self, id, value):
117d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        if 'intValues' not in self.store:
118d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            self.store.intValues = []
119d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        d = collections.OrderedDict()
120d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        d['id'] = id
121d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        d['value'] = value
122d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.store.intValues.append(d)
123d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self
124d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
125d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def intValues(self):
126d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        if 'intValues' not in self.store:
127d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            return []
128d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        for value in self.store.intValues:
129d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            yield (value['id'], value['value'])
130d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
131d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def setFloatValue(self, id, value):
132d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        if 'floatValues' not in self.store:
133d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            self.store.floatValues = []
134d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        d = collections.OrderedDict()
135d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        d['id'] = id
136d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        d['value'] = value
137d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        self.store.floatValues.append(d)
138d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self
139d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
140d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def floatValues(self):
141d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        if 'floatValues' not in self.store:
142d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            return []
143d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        for value in self.store.floatValues:
144d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            yield (value['id'], value['value'])
145d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
146d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    @classmethod
147d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def fromJson(cls, json):
148d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event = Event()
149d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event.setTimestamp(json.timestamp)
150d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event.setType(json.type)
151d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        for intValue in json.intValues:
152d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            event.setIntValue(intValue.id, intValue.value)
153d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        for floatValue in json.floatValues:
154d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            event.setFloatValue(floatValue.id, floatValue.value)
155d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event.setStringValue(json.stringValue)
156d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return event
157d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
158d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def transform(self, intMapping, floatMapping):
159d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event = Event()
160d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event.setTimestamp(self.getTimestamp())
161d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event.setType(self.getType())
162d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        for id, value in self.intValues():
163d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            if id in intMapping:
164d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata                intMapping[id](event, value)
165d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            else:
166d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata                print('warning: integer id 0x%x not found in mapping. dropped.' % id)
167d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        for id, value in self.floatValues():
168d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            if id in floatMapping:
169d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata                floatMapping[id](event, value)
170d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            else:
171d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata                print('warning: float id 0x%x not found in mapping. dropped.' % id)
172d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        event.setStringValue(self.getStringValue())
173d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return event
174d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
175d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def getStore(self):
176d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        return self.store.getStore()
177d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
178d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataclass EventEncoder(json.JSONEncoder):
179d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    def default(self, o):
180d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        if isinstance(o, Event):
181d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata            return o.getStore()
182d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
183d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# Mappings between standard OBD2 sensors and the indices
184d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata# used by Vehicle HAL
185d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico GranataintSensorsMapping = {
186d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x03 : lambda event,value: event.setIntValue(0, value),
187d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x05 : lambda event,value: event.setFloatValue(1, value),
188d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x0A : lambda event,value: event.setIntValue(22, value),
189d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x0C : lambda event,value: event.setFloatValue(8, value),
190d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x0D : lambda event,value: event.setFloatValue(9, value),
191d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x1F : lambda event,value: event.setIntValue(7, value),
192d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x5C : lambda event,value: event.setIntValue(23, value),
193d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata}
194d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
195d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico GranatafloatSensorsMapping = {
196d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x04 : lambda event, value: event.setFloatValue(0, value),
197d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x06 : lambda event, value: event.setFloatValue(2, value),
198d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x07 : lambda event, value: event.setFloatValue(3, value),
199d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x08 : lambda event, value: event.setFloatValue(4, value),
200d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x09 : lambda event, value: event.setFloatValue(5, value),
201d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x11 : lambda event, value: event.setFloatValue(12, value),
202d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x2F : lambda event, value: event.setFloatValue(42, value),
203d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    0x46 : lambda event, value: event.setIntValue(13, int(value)),
204d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata}
205d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
206d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granatadef parseOptions():
207d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    from argparse import ArgumentParser
208d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    parser = ArgumentParser(description='OBD2 to Diagnostics JSON Converter')
209d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    parser.add_argument('--src', '-S', dest='source_file',
210d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        help='The source file to convert from', required=True)
211d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    parser.add_argument('--dst', '-D', dest='destination_file',
212d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata        help='The destination file to convert to', required=True)
213d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    return parser.parse_args()
214d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
215d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataargs = parseOptions()
216d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granataif not os.path.exists(args.source_file):
217d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    print('source file %s does not exist' % args.source_file)
218d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    sys.exit(1)
219d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
220d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granatasource_json = Json.load(open(args.source_file))
221d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granatadest_events = []
222d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
223d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granatafor source_json_event in source_json:
224d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    source_event = Event.fromJson(source_json_event)
225d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    destination_event = source_event.transform(intSensorsMapping, floatSensorsMapping)
226d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata    dest_events.append(destination_event)
227d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granata
228d9a55214c87540d38f2fa146fba2be2a1cfc1886Enrico Granatajson.dump(dest_events, open(args.destination_file, 'w'), cls=EventEncoder)
229