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