diff --git a/app/ocpp_proto/chargepoint.py b/app/ocpp_proto/chargepoint.py index b82a06d..4e5fc09 100644 --- a/app/ocpp_proto/chargepoint.py +++ b/app/ocpp_proto/chargepoint.py @@ -1,85 +1,27 @@ from datetime import datetime, UTC import os -from uuid import UUID from ocpp.routing import on, after from ocpp.v201 import ChargePoint as cp from ocpp.v201 import call_result -from ocpp.v201.datatypes import IdTokenInfoType, IdTokenType -from ocpp.v201.enums import Action, RegistrationStatusType, AuthorizationStatusType, IdTokenType as IdTokenEnumType, TransactionEventType +from ocpp.v201.enums import Action, RegistrationStatusType, TransactionEventType from ocpp.v201.call import GetBaseReportPayload -from app.database import SessionLocal -from app.models.chargepoint import ChargePoint as DbChargePoint -from app.models.connector import Connector as DbConnector -from app.models.id_token import IdToken as DbIdToken -from app.models.transaction import Transaction as DbTransaction -from app.models.meter_value import MeterValue as DbMeterValue -from app.schemas.connector import ConnectorStatus -from app.schemas.transaction import TransactionStatus, TransactionEventTriggerReason -from app.schemas.meter_value import Measurand, PhaseType -from app.ocpp_proto.variable_manager import create_or_update_variable +from app.services import ( + variable_service, + id_token_service, + chargepoint_service, + transaction_service +) class ChargePoint(cp): - - async def __update_last_seen(self): - with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.identity == self.id).first() - db_chargepoint.last_seen = datetime.now(UTC) - db.commit() - - async def __get_id_token_info(self, id_token): - owner_id = None - if id_token["type"] not in ["ISO14443", "ISO15693"]: - return IdTokenInfoType( - status=AuthorizationStatusType.invalid - ), owner_id - - with SessionLocal() as db: - db_id_token = db.query(DbIdToken).filter(DbIdToken.token == id_token["id_token"]).first() - if db_id_token == None: - id_token_info = IdTokenInfoType( - status=AuthorizationStatusType.unknown - ) - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.identity == self.id).first() - # Learn token if requested - if db_chargepoint.learn_user_id != None: - if db_chargepoint.learn_until.timestamp() > datetime.now(UTC).timestamp(): - db_id_token = DbIdToken() - db_id_token.friendly_name = "New token learned by {}".format(self.id) - db_id_token.is_active = True - db_id_token.owner_id = db_chargepoint.learn_user_id - db_id_token.token = id_token["id_token"] - db.add(db_id_token) - - id_token_info=IdTokenInfoType( - status=AuthorizationStatusType.accepted - ) - owner_id = db_id_token.owner_id - db_chargepoint.learn_user_id = None - db_chargepoint.learn_until = None - db.commit() - else: - owner_id = db_id_token.owner_id - if db_id_token.is_active == False: - id_token_info=IdTokenInfoType( - status=AuthorizationStatusType.blocked - ) - else: - id_token_info=IdTokenInfoType( - status=AuthorizationStatusType.accepted - ) - return id_token_info, owner_id @on(Action.BootNotification) async def on_boot_notification(self, charging_station, **kwargs): - with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.identity == self.id).first() - db_chargepoint.last_seen = datetime.now(UTC) - for key in charging_station.keys(): - if key in db_chargepoint.__dict__: - setattr(db_chargepoint, key, charging_station[key]) - db.commit() + await chargepoint_service.update_attributes( + chargepoint_identity=self.id, + charging_station=charging_station + ) return call_result.BootNotificationPayload( current_time=datetime.now(UTC).isoformat(), interval=int(os.getenv("CS_HEARTBEAT_INTERVAL", "1800")), @@ -92,52 +34,36 @@ class ChargePoint(cp): @on(Action.NotifyReport) async def on_notify_report(self, report_data, **kwargs): - with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.identity == self.id).first() - for entry in report_data: - await create_or_update_variable( - chargepoint_id=db_chargepoint.id, - report_data=entry - ) + for entry in report_data: + await variable_service.create_or_update_variable( + chargepoint_identity=self.id, + report_entry=entry + ) return call_result.NotifyReportPayload() @on(Action.Heartbeat) async def on_heartbeat_request(self): - await self.__update_last_seen() return call_result.HeartbeatPayload( current_time=datetime.now(UTC).isoformat() ) + @after(Action.Heartbeat) + async def after_heartbeat_request(self): + await chargepoint_service.update_last_seen(chargepoint_identity=self.id) + @on(Action.StatusNotification) async def on_status_notification(self, evse_id: int, connector_id: int, connector_status: str, **kwargs): - with SessionLocal() as db: - db_chargepoint = db.query(DbChargePoint).filter(DbChargePoint.identity == self.id).first() - db_chargepoint.last_seen = datetime.now(UTC) - - db_connector = db.query(DbConnector).filter( - DbConnector.chargepoint_id == db_chargepoint.id, - DbConnector.evse == evse_id, - DbConnector.index == connector_id - ).first() - if db_connector == None: - db_connector = DbConnector( - chargepoint_id = db_chargepoint.id, - evse = evse_id, - index = connector_id, - status = ConnectorStatus(connector_status) - ) - db.add(db_connector) - else: - db_connector.status = ConnectorStatus(connector_status) - - db.commit() - + await chargepoint_service.create_or_update_connector( + chargepoint_identity=self.id, + evse_id=evse_id, + connector_id=connector_id, + connector_status=connector_status + ) return call_result.StatusNotificationPayload() @on(Action.Authorize) async def on_authorize(self, id_token, **kwargs): - await self.__update_last_seen() - id_token_info, _ = await self.__get_id_token_info(id_token) + id_token_info, _ = await id_token_service.get_id_token_info(chargepoint_id=self.id, id_token=id_token) return call_result.AuthorizePayload(id_token_info) @on(Action.TransactionEvent) @@ -149,86 +75,39 @@ class ChargePoint(cp): transaction_info, **kwargs ): + if "id_token" in kwargs.keys(): - id_token_info, token_owner_id = await self.__get_id_token_info(kwargs['id_token']) + id_token_info, token_owner_id = await id_token_service.get_id_token_info(chargepoint_id=self.id, id_token=kwargs['id_token']) + else: + id_token_info = None + token_owner_id = None - with SessionLocal() as db: - chargepoint = db.query(DbChargePoint).filter(DbChargePoint.identity == self.id).first() - chargepoint.last_seen = datetime.now(UTC) + if event_type == str(TransactionEventType.started): + await transaction_service.create_transaction( + chargepoint_identity=self.id, + user_id=token_owner_id, + timestamp=datetime.fromisoformat(timestamp), + transaction_info=transaction_info, + transaction_data=kwargs + ) + elif event_type == str(TransactionEventType.updated): + await transaction_service.update_transaction( + transaction_id=transaction_info["transaction_id"], + transaction_data=kwargs + ) + elif event_type == str(TransactionEventType.ended): + await transaction_service.end_transaction( + transaction_id=transaction_info["transaction_id"], + timestamp=datetime.fromisoformat(timestamp), + trigger_reason=trigger_reason, + transaction_data=kwargs, + user_id=token_owner_id + ) - if event_type == str(TransactionEventType.started): - meter_start=0 - if "meter_value" in kwargs.keys(): - for meter_value_entry in kwargs['meter_value']: - for sampled_value in meter_value_entry['sampled_value']: - if "measurand" in sampled_value.keys(): - if sampled_value['measurand'] == str(Measurand.ENERGY_ACTIVE_IMPORT_REGISTER): - meter_start = sampled_value['value'] - else: - meter_start = sampled_value['value'] - transaction = DbTransaction( - id=transaction_info["transaction_id"], - status=TransactionStatus.ONGOING, - started_at=datetime.fromisoformat(timestamp), - meter_start=meter_start, - price=chargepoint.price, - chargepoint_id=chargepoint.id - ) - if "id_token" in kwargs.keys(): - if id_token_info.status == AuthorizationStatusType.accepted: - transaction.user_id = token_owner_id - db.add(transaction) - elif event_type == str(TransactionEventType.updated): - transaction = db.get(DbTransaction, transaction_info["transaction_id"]) - if transaction != None: - if transaction.status == TransactionStatus.ONGOING: - if "meter_value" in kwargs.keys(): - for meter_value_entry in kwargs['meter_value']: - timestamp = datetime.fromisoformat(meter_value_entry['timestamp']) - for sampled_value in meter_value_entry['sampled_value']: - db_meter_value = DbMeterValue() - db_meter_value.transaction_id = transaction.id - db_meter_value.timestamp = timestamp - if "measurand" in sampled_value.keys(): - db_meter_value.measurand = Measurand(sampled_value['measurand']) - else: - db_meter_value.measurand = Measurand.ENERGY_ACTIVE_IMPORT_REGISTER - if "phase" in sampled_value.keys(): - db_meter_value.phase_type = PhaseType(sampled_value['phase']) - if "unit_of_measure" in sampled_value.keys(): - if "unit" in sampled_value['unit_of_measure']: - db_meter_value.unit = sampled_value['unit_of_measure']['unit'] - else: - db_meter_value.unit = "Wh" - db_meter_value.value = sampled_value['value'] - db.add(db_meter_value) - if "id_token" in kwargs.keys(): - if id_token_info.status == AuthorizationStatusType.accepted: - transaction.user_id = token_owner_id - elif event_type == str(TransactionEventType.ended): - transaction = db.get(DbTransaction, transaction_info["transaction_id"]) - if transaction != None: - transaction.status = TransactionStatus.ENDED - transaction.ended_at = datetime.fromisoformat(timestamp) - transaction.end_reason = TransactionEventTriggerReason(trigger_reason) - meter_end=0 - if "meter_value" in kwargs.keys(): - for meter_value_entry in kwargs['meter_value']: - for sampled_value in meter_value_entry['sampled_value']: - if "measurand" in sampled_value.keys(): - if sampled_value['measurand'] == str(Measurand.ENERGY_ACTIVE_IMPORT_REGISTER): - meter_end = sampled_value['value'] - else: - meter_end = sampled_value['value'] - transaction.meter_end = meter_end - if "id_token" in kwargs.keys(): - if id_token_info.status == AuthorizationStatusType.accepted: - transaction.user_id = token_owner_id - db.commit() - - if "id_token" in kwargs.keys(): + if id_token_info == None: + return call_result.TransactionEventPayload() + else: return call_result.TransactionEventPayload(id_token_info=id_token_info) - return call_result.TransactionEventPayload() @on(Action.MeterValues) async def on_meter_values(self, **kwargs): diff --git a/app/ocpp_proto/variable_manager.py b/app/ocpp_proto/variable_manager.py deleted file mode 100644 index fb7c4b9..0000000 --- a/app/ocpp_proto/variable_manager.py +++ /dev/null @@ -1,64 +0,0 @@ -from decimal import Decimal -from uuid import UUID - -from app.database import SessionLocal -from app.models.chargepoint_variable import ChargepointVariable as DbChargepointVariable -from app.schemas.chargepoint_variable import AttributeType, DataType, MutabilityType - -async def create_or_update_variable(chargepoint_id: UUID, report_data): - with SessionLocal() as db: - for variable_attribute in report_data['variable_attribute']: - query = db.query(DbChargepointVariable).filter( - DbChargepointVariable.chargepoint_id == chargepoint_id, - DbChargepointVariable.component_name == report_data['component']['name'], - DbChargepointVariable.name == report_data['variable']['name'] - ) - if "instance" in report_data['component'].keys(): - query = query.filter(DbChargepointVariable.component_instance == report_data['component']['instance']) - if "evse" in report_data['component'].keys(): - query = query.filter(DbChargepointVariable.evse == report_data['component']['evse']['id']) - if "connectorId" in report_data['component']['evse'].keys(): - query = query.filter(DbChargepointVariable.connector_id == report_data['component']['evse']['connectorId']) - if "type" in variable_attribute.keys(): - query = query.filter(DbChargepointVariable.type == AttributeType(variable_attribute['type'])) - else: - query = query.filter(DbChargepointVariable.type == AttributeType.ACTUAL) - db_variable = query.first() - if db_variable == None: - db_variable = DbChargepointVariable() - db_variable.chargepoint_id = chargepoint_id - db_variable.component_name = report_data['component']['name'] - db_variable.name = report_data['variable']['name'] - - if "value" in variable_attribute.keys(): - db_variable.value = variable_attribute['value'] - if "instance" in report_data['component'].keys(): - db_variable.component_instance = report_data['component']['instance'] - if "evse" in report_data['component'].keys(): - db_variable.evse = report_data['component']['evse']['id'] - if "connector_id" in report_data['component']['evse'].keys(): - db_variable.connector_id = report_data['component']['evse']['connector_id'] - if "constant" in variable_attribute.keys(): - db_variable.constant = variable_attribute['constant'] - if "persistent" in variable_attribute.keys(): - db_variable.constant = variable_attribute['persistent'] - if "mutability" in variable_attribute.keys(): - db_variable.mutability = MutabilityType(variable_attribute['mutability']) - if "type" in variable_attribute.keys(): - db_variable.type = AttributeType(variable_attribute['type']) - if "variable_characteristics" in report_data.keys(): - db_variable.data_type = DataType(report_data['variable_characteristics']['data_type']) - if "min_limit" in report_data['variable_characteristics'].keys(): - db_variable.min_limit = Decimal(report_data['variable_characteristics']['min_limit']) - if "max_limit" in report_data['variable_characteristics'].keys(): - db_variable.max_limit = Decimal(report_data['variable_characteristics']['max_limit']) - if "unit" in report_data['variable_characteristics'].keys(): - db_variable.unit = report_data['variable_characteristics']['unit'] - if "values_list" in report_data['variable_characteristics'].keys(): - db_variable.values_list = report_data['variable_characteristics']['values_list'] - db.add(db_variable) - else: - if "value" in variable_attribute.keys(): - db_variable.value = variable_attribute['value'] - db.commit() - \ No newline at end of file diff --git a/app/services/__init__.py b/app/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/services/chargepoint_service.py b/app/services/chargepoint_service.py new file mode 100644 index 0000000..502ff46 --- /dev/null +++ b/app/services/chargepoint_service.py @@ -0,0 +1,46 @@ +from datetime import datetime, UTC + +from app.database import SessionLocal +from app.models.chargepoint import ChargePoint +from app.models.connector import Connector + +from app.schemas.connector import ConnectorStatus + +async def update_last_seen(chargepoint_identity: str): + with SessionLocal() as db: + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.identity == chargepoint_identity).first() + db_chargepoint.last_seen = datetime.now(UTC) + db.commit() + +async def update_attributes(chargepoint_identity: str, charging_station): + with SessionLocal() as db: + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.identity == chargepoint_identity).first() + for key in charging_station.keys(): + if key in db_chargepoint.__dict__: + setattr(db_chargepoint, key, charging_station[key]) + db.commit() + +async def create_or_update_connector( + chargepoint_identity: str, + evse_id: int, + connector_id: int, + connector_status: str +): + with SessionLocal() as db: + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.identity == chargepoint_identity).first() + db_connector = db.query(Connector).filter( + Connector.chargepoint_id == db_chargepoint.id, + Connector.evse == evse_id, + Connector.index == connector_id + ).first() + if db_connector == None: + db_connector = Connector( + chargepoint_id = db_chargepoint.id, + evse = evse_id, + index = connector_id, + status = ConnectorStatus(connector_status) + ) + db.add(db_connector) + else: + db_connector.status = ConnectorStatus(connector_status) + db.commit() \ No newline at end of file diff --git a/app/services/id_token_service.py b/app/services/id_token_service.py new file mode 100644 index 0000000..7a9c4fe --- /dev/null +++ b/app/services/id_token_service.py @@ -0,0 +1,51 @@ +from datetime import datetime, UTC + +from ocpp.v201.datatypes import IdTokenInfoType +from ocpp.v201.enums import AuthorizationStatusType + +from app.database import SessionLocal +from app.models.id_token import IdToken +from app.models.chargepoint import ChargePoint + +async def get_id_token_info(chargepoint_id: str, id_token: str): + owner_id = None + if id_token["type"] not in ["ISO14443", "ISO15693"]: + return IdTokenInfoType( + status=AuthorizationStatusType.invalid + ), owner_id + + with SessionLocal() as db: + db_id_token = db.query(IdToken).filter(IdToken.token == id_token["id_token"]).first() + if db_id_token == None: + id_token_info = IdTokenInfoType( + status=AuthorizationStatusType.unknown + ) + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.identity == chargepoint_id).first() + # Learn token if requested + if db_chargepoint.learn_user_id != None: + if db_chargepoint.learn_until.timestamp() > datetime.now(UTC).timestamp(): + db_id_token = IdToken() + db_id_token.friendly_name = "New token learned by {}".format(chargepoint_id) + db_id_token.is_active = True + db_id_token.owner_id = db_chargepoint.learn_user_id + db_id_token.token = id_token["id_token"] + db.add(db_id_token) + + id_token_info=IdTokenInfoType( + status=AuthorizationStatusType.accepted + ) + owner_id = db_id_token.owner_id + db_chargepoint.learn_user_id = None + db_chargepoint.learn_until = None + db.commit() + else: + owner_id = db_id_token.owner_id + if db_id_token.is_active == False: + id_token_info=IdTokenInfoType( + status=AuthorizationStatusType.blocked + ) + else: + id_token_info=IdTokenInfoType( + status=AuthorizationStatusType.accepted + ) + return id_token_info, owner_id \ No newline at end of file diff --git a/app/services/meter_value_service.py b/app/services/meter_value_service.py new file mode 100644 index 0000000..8791311 --- /dev/null +++ b/app/services/meter_value_service.py @@ -0,0 +1,30 @@ + +from datetime import datetime +from uuid import UUID + +from app.database import SessionLocal +from app.models.meter_value import MeterValue + +from app.schemas.meter_value import Measurand, PhaseType + +async def create_meter_value(transaction_id: UUID, meter_value_data): + with SessionLocal() as db: + timestamp = datetime.fromisoformat(meter_value_data['timestamp']) + for sampled_value in meter_value_data['sampled_value']: + db_meter_value = MeterValue() + db_meter_value.transaction_id = transaction_id + db_meter_value.timestamp = timestamp + if "measurand" in sampled_value.keys(): + db_meter_value.measurand = Measurand(sampled_value['measurand']) + else: + db_meter_value.measurand = Measurand.ENERGY_ACTIVE_IMPORT_REGISTER + if "phase" in sampled_value.keys(): + db_meter_value.phase_type = PhaseType(sampled_value['phase']) + if "unit_of_measure" in sampled_value.keys(): + if "unit" in sampled_value['unit_of_measure']: + db_meter_value.unit = sampled_value['unit_of_measure']['unit'] + else: + db_meter_value.unit = "Wh" + db_meter_value.value = sampled_value['value'] + db.add(db_meter_value) + db.commit() diff --git a/app/services/transaction_service.py b/app/services/transaction_service.py new file mode 100644 index 0000000..d8719b4 --- /dev/null +++ b/app/services/transaction_service.py @@ -0,0 +1,86 @@ +from datetime import datetime +from typing import Optional +from uuid import UUID + +from app.database import SessionLocal +from app.models.chargepoint import ChargePoint +from app.models.transaction import Transaction + +from app.schemas.meter_value import Measurand +from app.schemas.transaction import TransactionEventTriggerReason, TransactionStatus + +from app.services import meter_value_service + +async def create_transaction( + chargepoint_identity: str, + user_id: UUID, + timestamp: datetime, + transaction_info, + transaction_data +): + with SessionLocal() as db: + chargepoint = db.query(ChargePoint).filter(ChargePoint.identity == chargepoint_identity).first() + meter_start=0 + if "meter_value" in transaction_data.keys(): + for meter_value_entry in transaction_data['meter_value']: + for sampled_value in meter_value_entry['sampled_value']: + if "measurand" in sampled_value.keys(): + if sampled_value['measurand'] == str(Measurand.ENERGY_ACTIVE_IMPORT_REGISTER): + meter_start = sampled_value['value'] + else: + meter_start = sampled_value['value'] + transaction = Transaction( + id=transaction_info["transaction_id"], + status=TransactionStatus.ONGOING, + started_at=timestamp, + meter_start=meter_start, + price=chargepoint.price, + chargepoint_id=chargepoint.id, + user_id=user_id + ) + db.add(transaction) + db.commit() + +async def update_transaction( + transaction_id: str, + transaction_data +): + with SessionLocal() as db: + transaction = db.get(Transaction, transaction_id) + if transaction != None: + if transaction.status == TransactionStatus.ONGOING: + if "meter_value" in transaction_data.keys(): + for meter_value_entry in transaction_data['meter_value']: + await meter_value_service.create_meter_value( + transaction_id=transaction.id, + meter_value_data=meter_value_entry + ) + +async def end_transaction( + transaction_id: str, + timestamp: datetime, + trigger_reason: str, + transaction_data, + user_id: Optional[UUID] +): + with SessionLocal() as db: + transaction = db.get(Transaction, transaction_id) + if transaction != None: + meter_end=0 + if "meter_value" in transaction_data.keys(): + for meter_value_entry in transaction_data['meter_value']: + for sampled_value in meter_value_entry['sampled_value']: + if "measurand" in sampled_value.keys(): + if sampled_value['measurand'] == str(Measurand.ENERGY_ACTIVE_IMPORT_REGISTER): + meter_end = sampled_value['value'] + else: + meter_end = sampled_value['value'] + + transaction.status = TransactionStatus.ENDED + transaction.ended_at = timestamp + transaction.end_reason = TransactionEventTriggerReason(trigger_reason) + transaction.meter_end = meter_end + + if user_id != None: + transaction.user_id = user_id + db.commit() \ No newline at end of file diff --git a/app/services/variable_service.py b/app/services/variable_service.py new file mode 100644 index 0000000..2f25b57 --- /dev/null +++ b/app/services/variable_service.py @@ -0,0 +1,66 @@ +from decimal import Decimal + +from app.database import SessionLocal +from app.models.chargepoint import ChargePoint +from app.models.chargepoint_variable import ChargepointVariable + +from app.schemas.chargepoint_variable import AttributeType, DataType, MutabilityType + +async def create_or_update_variable(chargepoint_identity: str, report_entry): + with SessionLocal() as db: + db_chargepoint = db.query(ChargePoint).filter(ChargePoint.identity == chargepoint_identity).first() + for variable_attribute in report_entry['variable_attribute']: + query = db.query(ChargepointVariable).filter( + ChargepointVariable.chargepoint_id == db_chargepoint.id, + ChargepointVariable.component_name == report_entry['component']['name'], + ChargepointVariable.name == report_entry['variable']['name'] + ) + if "instance" in report_entry['component'].keys(): + query = query.filter(ChargepointVariable.component_instance == report_entry['component']['instance']) + if "evse" in report_entry['component'].keys(): + query = query.filter(ChargepointVariable.evse == report_entry['component']['evse']['id']) + if "connectorId" in report_entry['component']['evse'].keys(): + query = query.filter(ChargepointVariable.connector_id == report_entry['component']['evse']['connectorId']) + if "type" in variable_attribute.keys(): + query = query.filter(ChargepointVariable.type == AttributeType(variable_attribute['type'])) + else: + query = query.filter(ChargepointVariable.type == AttributeType.ACTUAL) + db_variable = query.first() + if db_variable == None: + db_variable = ChargepointVariable() + db_variable.chargepoint_id = db_chargepoint.id + db_variable.component_name = report_entry['component']['name'] + db_variable.name = report_entry['variable']['name'] + + if "value" in variable_attribute.keys(): + db_variable.value = variable_attribute['value'] + if "instance" in report_entry['component'].keys(): + db_variable.component_instance = report_entry['component']['instance'] + if "evse" in report_entry['component'].keys(): + db_variable.evse = report_entry['component']['evse']['id'] + if "connector_id" in report_entry['component']['evse'].keys(): + db_variable.connector_id = report_entry['component']['evse']['connector_id'] + if "constant" in variable_attribute.keys(): + db_variable.constant = variable_attribute['constant'] + if "persistent" in variable_attribute.keys(): + db_variable.constant = variable_attribute['persistent'] + if "mutability" in variable_attribute.keys(): + db_variable.mutability = MutabilityType(variable_attribute['mutability']) + if "type" in variable_attribute.keys(): + db_variable.type = AttributeType(variable_attribute['type']) + if "variable_characteristics" in report_entry.keys(): + db_variable.data_type = DataType(report_entry['variable_characteristics']['data_type']) + if "min_limit" in report_entry['variable_characteristics'].keys(): + db_variable.min_limit = Decimal(report_entry['variable_characteristics']['min_limit']) + if "max_limit" in report_entry['variable_characteristics'].keys(): + db_variable.max_limit = Decimal(report_entry['variable_characteristics']['max_limit']) + if "unit" in report_entry['variable_characteristics'].keys(): + db_variable.unit = report_entry['variable_characteristics']['unit'] + if "values_list" in report_entry['variable_characteristics'].keys(): + db_variable.values_list = report_entry['variable_characteristics']['values_list'] + db.add(db_variable) + else: + if "value" in variable_attribute.keys(): + db_variable.value = variable_attribute['value'] + db.commit() + \ No newline at end of file