123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- ##########################################################################################################################################
- # Python-File Information #
- ##########################################################################################################################################
- #
- # File: Xcom_API.py
- # Author: Tobias Müller
- # Date: 2017.08.09
- #
- ##########################################################################################################################################
- # Requirements #
- ##########################################################################################################################################
- import struct
- ##########################################################################################################################################
- # Class Definition & Description #
- ##########################################################################################################################################
- # This class is used to generate byte-frames, which are needed to communicate with Xtender-Moduls over the RS232-BUS with the Xcom-232i.
- # After generating the byte-frame, you can use "pyserial" to communicate with the Serial-BUS and to put the byte-frame into the write-
- # method of "pyserial". You can decode also read-frames of the Serial-BUS with this class.
- #
- # This class contains methods to generate read- or write-frames, and methods to decode frames. There are pre-defined types, properties
- # and formats for the most important parameter- and information-numbers. This reduces the effort for generating byte-frames, but there
- # are extended methods to generate byte-frames with other parameter- and information-numbers.
- class Xcom_API():
- """
- This class is used to generate byte-frames, which are needed to communicate with Xtender-Moduls over the RS232-BUS with the Xcom-232i.
- After generating the byte-frame, you can use "pyserial" to communicate with the Serial-BUS and to put the byte-frame into the write-
- method of "pyserial". You can decode also read-frames of the Serial-BUS with this class.
- This class contains methods to generate read- or write-frames, and methods to decode frames. There are pre-defined types, properties
- and formats for the most important parameter- and information-numbers. This reduces the effort for generating byte-frames, but there
- are extended methods to generate byte-frames with other parameter- and information-numbers.
- """
- ##################################################################################################################################
- # Program Information #
- ##################################################################################################################################
- __PROG_NAME = 'Xcom_API'
- __PROG_Version = 'v1.0'
- ##################################################################################################################################
- # Private-Object-Instance-Counter #
- ##################################################################################################################################
- __object_counter = 0
- ##################################################################################################################################
- # Private-Attributes-Service_ID #
- ##################################################################################################################################
- __service_read = 1
- __service_write = 2
- ##################################################################################################################################
- # Protected-Attributes-Object_Type #
- ##################################################################################################################################
- _object_type_info = 1
- _object_type_parameter = 2
- _object_type_message = 3
- _object_type_datalog_field = 5
- _object_type_datalog_transfer = 257
- ##################################################################################################################################
- # Protected-Attributes-Info-Object_ID #
- ##################################################################################################################################
- _info_battery_voltage = 3000
- _info_battery_temperature = 3001
- _info_battery_charge_current = 3005
- _info_battery_voltage_ripple = 3006
- _info_state_of_charge = 3007
- _info_number_of_battery_elements = 3050
- _info_input_voltage = 3011
- _info_input_current = 3012
- _info_input_frequency = 3084
- _info_input_power = 3138
- _info_output_voltage = 3021
- _info_output_current = 3022
- _info_output_frequency = 3085
- _info_output_power = 3139
- _info_operating_state = 3028
- _info_boost_active = 3019
- _info_state_of_inverter = 3049
- _info_state_of_transfer_relay = 3020
- _info_state_of_output_relay = 3030
- _info_state_of_aux_relay_1 = 3031
- _info_state_of_aux_relay_2 = 3032
- _info_state_of_ground_relay = 3074
- _info_state_of_neutral_transfer_relay = 3075
- _info_state_of_remote_entry = 3086
- _info_battery_voltage_slr = 11000
- _info_battery_charge_current_slr = 11001
- _info_pv_voltage_slr = 11002
- _info_pv_power_slr = 11004
- _info_operation_mode_slr = 11016
- _info_type_of_error_slr = 11034
- _info_battery_cycle_phase_slr = 11038
- _info_state_variotrack_slr = 11069
- ##################################################################################################################################
- # Protected-Attributes-Parameter-Object_ID #
- ##################################################################################################################################
- _para_maximum_current_of_ac_source = 1107
- _para_battery_charge_current = 1138
- _para_smart_boost_allowed = 1126
- _para_inverter_allowed = 1124
- _para_type_of_detection_of_grid_loss = 1552
- _para_charger_allowed = 1125
- _para_charger_uses_only_power_from_ac = 1646
- _para_ac_output_voltage = 1286
- _para_inverter_frequency = 1112
- _para_transfer_relay_allowed = 1128
- _para_limitation_of_the_power_boost = 1607
- _para_remote_entry_active = 1545
- _para_battery_charge_current_slr = 10002
- _para_battery_undervoltage_slr = 10334
- _para_operating_mode_aux_1_slr = 10089
-
- ##################################################################################################################################
- # Protected-Attributes-Property_ID #
- ##################################################################################################################################
- _property_id_value = 1
- _property_id_string = 1
- _property_id_value_qsp = 5
- _property_id_min_qsp = 6
- _property_id_max_qsp = 7
- _property_id_level_qsp = 8
- _property_id_unsaved_value_qsp = 13
- _property_id_invalid_Action = 0
- _property_id_sd_start = 21
- _property_id_sd_datablock = 22
- _property_id_sd_ack_continue = 23
- _property_id_sd_nack_retry = 24
- _property_id_sd_abort = 25
- _property_id_sd_finish = 26
- ##################################################################################################################################
- # Protected-Attributes-Format #
- ##################################################################################################################################
- _format_bool = [1,1]
- _format_format = [2,2]
- _format_short_int = [3,2]
- _format_enum = [4,2]
- _format_short_enum = [5,2]
- _format_long_enum = [6,4]
- _format_error = [7,2]
- _format_int32 = [8,4]
- _format_float = [9,4]
- _format_byte = [10,1]
- ##################################################################################################################################
- # Private-Level-QSP #
- ##################################################################################################################################
-
- __level_qsp_view_only = 0x0000
- __level_qsp_basic = 0x0010
- __level_qsp_expert = 0x0020
- __level_qsp_installer = 0x0030
- __level_qsp_qsp = 0x0040
- ##################################################################################################################################
- # Private-Attributes #
- ##################################################################################################################################
-
- __start_byte = 0xAA
- __frame_flags = 0x00
- __data_flags = 0x00
- __data_frame = 0x0A
- # Dictionary of Error-Codes-Descriptions
- __error_code_dict = {0x0001 : 'INVALID_FRAME',
- 0x0002 : 'DEVICE_NOT_FOUND',
- 0x0003 : 'RESPONSE_TIMEOUT',
- 0x0011 : 'SERVICE_NOT_SUPPORTED',
- 0x0012 : 'INVALID_SERVICE_ARGUMENT',
- 0x0013 : 'SCOM_ERROR_GATEWAY_BUSY',
- 0x0021 : 'TYPE_NOT_SUPPORTED',
- 0x0022 : 'OBJECT_ID_NOT_FOUND',
- 0x0023 : 'PROPERTY_NOT_SUPPORTED',
- 0x0024 : 'INVALID_DATA_LENGTH',
- 0x0025 : 'PROPERTY_IS_READ_ONLY',
- 0x0026 : 'INVALID_DATA',
- 0x0027 : 'DATA_TOO_SMALL',
- 0x0028 : 'DATA_TO_BIG',
- 0x0029 : 'WRITE_PROPERTY_FAILED',
- 0x002A : 'READ_PROPERTY_FAILED',
- 0X002B : 'ACCESS_DENIED',
- 0x002C : 'SCOM_ERROR_OBJECT_NOT_SUPPORTED',
- 0x002D : 'SCOM_ERROR_MULTICAST_READ_NOT_SUPPORTED',
- 0x002E : 'OBJECT_PROPERTY_INVALID',
- 0x002F : 'FILE_OR_DIR_NOT_PRESENT',
- 0x0030 : 'FILE_CORRUPTED',
- 0x0081 : 'INVALID_SHELL_ARG'}
- # Dictionary of Parameter-Info-Numbers with type, property and format
- __para_info_dict = {3000 : [_object_type_info,_property_id_value,_format_float],
- 3001 : [_object_type_info,_property_id_value,_format_float],
- 3005 : [_object_type_info,_property_id_value,_format_float],
- 3006 : [_object_type_info,_property_id_value,_format_float],
- 3007 : [_object_type_info,_property_id_value,_format_float],
- 3050 : [_object_type_info,_property_id_value,_format_float],
- 3011 : [_object_type_info,_property_id_value,_format_float],
- 3012 : [_object_type_info,_property_id_value,_format_float],
- 3084 : [_object_type_info,_property_id_value,_format_float],
- 3138 : [_object_type_info,_property_id_value,_format_float],
- 3020 : [_object_type_info,_property_id_value,_format_short_enum],
- 3021 : [_object_type_info,_property_id_value,_format_float],
- 3022 : [_object_type_info,_property_id_value,_format_float],
- 3085 : [_object_type_info,_property_id_value,_format_float],
- 3139 : [_object_type_info,_property_id_value,_format_float],
- 3028 : [_object_type_info,_property_id_value,_format_short_enum],
- 3019 : [_object_type_info,_property_id_value,_format_short_enum],
- 3049 : [_object_type_info,_property_id_value,_format_short_enum],
- 3030 : [_object_type_info,_property_id_value,_format_short_enum],
- 3031 : [_object_type_info,_property_id_value,_format_short_enum],
- 3032 : [_object_type_info,_property_id_value,_format_short_enum],
- 3074 : [_object_type_info,_property_id_value,_format_short_enum],
- 3075 : [_object_type_info,_property_id_value,_format_short_enum],
- 3086 : [_object_type_info,_property_id_value,_format_short_enum],
- 1107 : [_object_type_parameter,_property_id_value_qsp,_format_float],
- 1138 : [_object_type_parameter,_property_id_value_qsp,_format_float],
- 1126 : [_object_type_parameter,_property_id_value_qsp,_format_bool],
- 1124 : [_object_type_parameter,_property_id_value_qsp,_format_bool],
- 1552 : [_object_type_parameter,_property_id_value_qsp,_format_long_enum],
- 1125 : [_object_type_parameter,_property_id_value_qsp,_format_bool],
- 1646 : [_object_type_parameter,_property_id_value_qsp,_format_bool],
- 1286 : [_object_type_parameter,_property_id_value_qsp,_format_float],
- 1112 : [_object_type_parameter,_property_id_value_qsp,_format_float],
- 1128 : [_object_type_parameter,_property_id_value_qsp,_format_bool],
- 1607 : [_object_type_parameter,_property_id_value_qsp,_format_float],
- 1545 : [_object_type_parameter,_property_id_value_qsp,_format_long_enum],
- 10002 : [_object_type_parameter,_property_id_value,_format_float],
- 10334 : [_object_type_parameter,_property_id_value,_format_float],
- 10089 : [_object_type_parameter,_property_id_value,_format_long_enum],
- 11000 : [_object_type_info,_property_id_value,_format_float],
- 11001 : [_object_type_info,_property_id_value,_format_float],
- 11002 : [_object_type_info,_property_id_value,_format_float],
- 11004 : [_object_type_info,_property_id_value,_format_float],
- 11016 : [_object_type_info,_property_id_value,_format_short_enum],
- 11034 : [_object_type_info,_property_id_value,_format_short_enum],
- 11038 : [_object_type_info,_property_id_value,_format_short_enum],
- 11069 : [_object_type_info,_property_id_value,_format_short_enum]}
- ##################################################################################################################################
- # Constructor-Method #
- ##################################################################################################################################
- # This Method is used with generating an object of the Xcom_API-Class. There are pre-defined arguments (CRC-Check, source-address,
- # destination-address) for this object, when you generate an objects without relevant arguments.
- def __init__(self, crc = True, source = 1, destination = 101):
- """
- ### Description:
- This Method is used with generating an object of the Xcom_API-Class. There are predefined arguments (CRC-Check, source-address,
- destination-address) for this object, when you generate an objects without relevant arguments.
- ### Arguments:
- There are predefined arguments, which you can change:
- +-+-+
- | | |
- +=+=+
- | **crc** | = True |
- +-+-+
- | **source** | = 1 |
- +-+-+
- | **destination** | = 101 |
- +-+-+
- ### Return-Value:
- This Method return an object of the Xcom_API-Class.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- **Or if you want to change predefined arguments:**
- ```>>> Object = Xcom_API(crc = False)
- """
-
- # Check the type of the argument "crc". It raises a "ValueError" with a false type.
- if not isinstance(crc, bool):
- raise ValueError('CRC is not type \"bool\"!')
- # Check the type of the argument "source". It raises a "ValueError" with a false type.
- elif not isinstance(source, int) or isinstance(source, bool):
- raise ValueError('Source-Address is not type \"int\"!')
- # Check the range of the argument "source" It raises a "ValueError", if the argument is out of range.
- elif not 0<source<100:
- raise ValueError('Source-Address is out of range!')
- # Check the type of the argument "destination" It raises a "ValueError" with a false type.
- elif not isinstance(destination, int) or isinstance(destination, bool):
- raise ValueError('Destination-Address is not type \"int\"!')
- # Check the range of the argument "destination" It raises a "ValueError", if the argument is out of range.
- elif not (destination==0 or destination==401 or destination==501 or destination==601 or 100<=destination<=109 or
- 191<=destination<=193 or 300<=destination<=315 or 700<=destination<=715):
- raise ValueError('Destination-Address is out of range!')
- # If there is no error, the arguments will be stored in variables of the object. The object-counter will be increased.
- else:
- self.__dest = destination
- self.__source = source
- self.__crc = crc
- self.__frame_check_done = False
- Xcom_API.__object_counter += 1
- ##################################################################################################################################
- # Deconstructor-Method #
- ##################################################################################################################################
- # This Method delete an object of this class with the stored variables and decrease the object-counter.
- def __del__(self):
- """
- ### Description:
- This Method delete an object of this class with the stored variables and decrease the object-counter.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> del Object
- """
- if hasattr(self,'__crc'):
- del self.__crc
- if hasattr(self,'__source'):
- del self.__source
- if hasattr(self,'__dest'):
- del self.__dest
- if hasattr(self,'__frame_check_done'):
- del self.__frame_check_done
- Xcom_API.__object_counter -= 1
- ##################################################################################################################################
- # Information-Methods #
- ##################################################################################################################################
- # This method returns an integer-value of the source-address of an object.
- def get_source_address(self):
- """
- ### Description:
- This method returns an integer-value of the source-address of an object.
- ### Return-Value:
- This Method return an **int**.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Src_Addr = Object.get_source_address()
- >>> Src_Addr
- 1
- """
- return self.__source
- # This method returns an integer-value of the destination-address of an object.
-
- def get_destination_address(self):
- """
- ### Description:
- This method returns an integer-value of the destination-address of an object.
- ### Return-Value:
- This Method return an **int**.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Dest_Addr = Object.get_destination_address()
- >>> Dest_Addr
- 101
- """
- return self.__dest
- # This method returns a boolean-value of the active-state of the CRC-Check of an object.
- def is_crc_check_active(self):
- """
- ### Description:
- This method returns a boolean-value of the active-state of the CRC-Check of an object.
- ### Return-Value:
- This Method return a **boolean**.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> CRC_Active = Object.is_crc_check_active()
- >>> CRC_Active
- True
- """
- return self.__crc
- # This method returns a integer-value of the counter of active-objects of this class.
- @staticmethod
- def get_object_counter():
- """
- ### Description:
- This method returns a integer-value of the counter of active-objects of this class.
- ### Return-Value:
- This Method return an **int**.
- ### Example-Code:
- ```>>> Obj_Count = Xcom_API.get_object_counter()
- >>> Obj_Count
- 0
- **Or if you have generate an Object:**
- ```>>> Object = Xcom_API()
- >>> Obj_Count = Object.get_object_counter()
- >>> Obj_Count
- 1
- """
- return Xcom_API.__object_counter
-
- # This method returns a string of the of the program-name of this class.
- @staticmethod
- def get_prog_name():
- """
- ### Description:
- This method returns a string of the of the program-name of this class.
- ### Return-Value:
- This Method return a **string**.
- ### Example-Code:
- ```>>> Prog_Name = Xcom_API.get_prog_name()
- >>> Prog_Name
- 'Xcom_API'
- **Or if you have generate an Object:**
- ```>>> Object = Xcom_API()
- >>> Prog_Name = Object.get_prog_name()
- >>> Prog_Name
- 'Xcom_API'
- """
- return Xcom_API.__PROG_NAME
- # This method returns a string of the of the program-version of this class.
- @staticmethod
- def get_prog_version():
- """
- ### Description:
- This method returns a string of the of the program-version of this class.
- ### Return-Value:
- This Method return a **string**.
- ### Example-Code:
- ```>>> Prog_Version = Xcom_API.get_prog_version
- >>> Prog_Version
- 'v1.0'
- **Or if you have generate an Object:**
- ```>>> Object = Xcom_API()
- >>> Prog_Version = Object.get_prog_version
- >>> Prog_Version
- 'v1.0'
- """
- return Xcom_API.__PROG_Version
- ##################################################################################################################################
- # Private-Methods #
- ##################################################################################################################################
- # This Method calculate the CRC-Values of a Frame. It returns the CRC-Values in a list or bytearray.
- def __calculate_checksum(byte_frame):
- """
- ### Description:
- This Method calculate the CRC-Values of a Frame. It returns the CRC-Values in a **list**.
- ### Arguments:
- The **<byte_frame>** argument must be a type of **list** or **bytearray**.
- ### Return-Value:
- This Method return a **list** of length two with the CRC-Values.
- ### Example-Code:
- ```>>> Byte_Frame = [0x0, 0x1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xA, 0x0]
- >>> CRC_Value = Xcom_API.__calculate_checksum(Byte_Frame)
- >>> CRC_Value
- [0x6F, 0x71]
- **Or if you are not using this function inside the API:**
- ```>>> Byte_Frame = [0x0, 0x1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xA, 0x0]
- >>> CRC_Value = Xcom_API._Xcom_API__calculate_checksum(Byte_Frame)
- >>> CRC_Value
- [0x6F, 0x71]
- """
- # Define two Buffers for the CRC-Values.
- Buffer1 = 0xFF
- Buffer2 = 0
- # Calculate the CRC-Values of a Frame.
- for i in range(0,len(byte_frame)):
- Buffer1 = (Buffer1 + byte_frame[i]) % 256
- Buffer2 = (Buffer1 + Buffer2) % 256
-
- # Return the CRC-Values in a list.
- return [Buffer1, Buffer2]
-
- # This Method generate a Byte-Frame of a Value depending of the format. It returns a list of Bytes, which are ordered in LSB to
- # MSB.
- def __value_to_byte_frame(property_data, data_format):
- """
- ### Description:
- This Method generate a Byte-Frame of a Value depending of the format. It returns a list of Bytes, which are ordered in LSB to MSB.
- ### Arguments:
- The **<property_data>** argument must be a type of **int** or **float** depending of the type of **<data_format>**.
- For the **<data_format>** argument use one of the following formats:
- +-+-+
- | | |
- +=+=+
- | _format_bool | = [1, 1] |
- +-+-+
- | _format_format | = [2, 2] |
- +-+-+
- | _format_short_int | = [3, 2] |
- +-+-+
- | _format_enum | = [4, 2] |
- +-+-+
- | _format_short_enum | = [5, 2] |
- +-+-+
- | _format_long_enum | = [6, 4] |
- +-+-+
- | _format_error | = [7, 2] |
- +-+-+
- | _format_int32 | = [8, 4] |
- +-+-+
- | _format_float | = [9, 4] |
- +-+-+
- | _format_byte | = [10, 1] |
- +-+-+
- ### Return-Value:
- This Method return a **list** with values, which represents the **Byte_Frame**. The length of the **list** depends of the **<data_format>** argument.
- ### Example-Code:
- ```>>> Value = 12.0
- >>> Byte_Frame = Xcom_API.__value_to_byte_frame(Value, Xcom_API._format_float)
- >>> Byte_Frame
- [0x0, 0x0, 0x40, 0x41]
- **Or if you are not using this function inside the API:**
- ```>>> Value = 12.0
- >>> Byte_Frame = Xcom_API._Xcom_API__value_to_byte_frame(Value, Xcom_API._format_float)
- >>> Byte_Frame
- [0x0, 0x0, 0x40, 0x41]
- """
- # It checks the argument "data_format" for type "Bool" and check the range/type of "property_data", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it returns the list of the Byte-Frame.
- if data_format==Xcom_API._format_bool:
- if not 0<=property_data<=1 or not (isinstance(property_data, int) or isinstance(property_data, bool)):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"bool\"!')
- else:
- # Return a list of the Byte-Frame.
- if property_data == 0 or property_data == False:
- return [0]
- else:
- return [1]
- # It checks the argument "data_format" for type "Byte" and check the range/type of "property_data", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it returns the list of the Byte-Frame.
- elif data_format==Xcom_API._format_byte:
- if not 0<=property_data<256 or not isinstance(property_data, int):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Byte\"!')
- else:
- # Return a list of the Byte-Frame.
- return [property_data]
-
- # It checks the argument "data_format" for type "Error" and check the range/type of "property_data", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the list of the Byte-Frame.
- elif data_format==Xcom_API._format_error:
- if not 0<=property_data<=0x65535 or not isinstance(property_data, int):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Error\"!')
- else:
- # Define a Buffer for calculating.
- Buffer = hex(property_data)
- # Calculate the Byte-Frame.
- for i in range(0,data_format[1]*2-(len(Buffer)-2)):
- Buffer = Buffer[0:2]+str(0)+Buffer[2:]
- # Return a list of the Byte-Frame.
- return [int(Buffer[4:6],16),int(Buffer[2:4],16)]
- # It checks the argument "data_format" for type "Format" or "Short Integer" and check the range/type of "property_data",
- # depending of the data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the list of
- # the Byte-Frame.
- elif data_format==Xcom_API._format_format or data_format==Xcom_API._format_short_int:
- if not -32768<=property_data<=32767 or not isinstance(property_data, int):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Format\" or \"Short Integer\"!')
- else:
- # Calculate the Byte-Frame.
- if property_data<0:
- # Define a Buffer for calculating.
- Buffer = hex(2**16 + property_data)
- else:
- # Define a Buffer for calculating.
- Buffer = hex(property_data)
- for i in range(0,data_format[1]*2-(len(Buffer)-2)):
- Buffer = Buffer[0:2]+str(0)+Buffer[2:]
- # Return a list of the Byte-Frame.
- return [int(Buffer[4:6],16),int(Buffer[2:4],16)]
- # It checks the argument "data_format" for type "Enum" or "Short Enum" and check the range/type of "property_data", depending
- # of the data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the list of the Byte-Frame.
- # Only one Bit can be set in data_format of type "Enum".
- elif data_format==Xcom_API._format_enum or data_format==Xcom_API._format_short_enum:
- if not 0<=property_data<=32767 or not isinstance(property_data, int):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Enum\" or \"Short Enum\"!')
- else:
- check = False
- for i in range(0,16):
- if (2**i==2**i&property_data) and check:
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Enum\" or \"Short Enum\"!')
- elif 2**i==2**i&property_data:
- check = True
- # Define a Buffer for calculating.
- Buffer = hex(property_data)
- # Calculate the Byte-Frame.
- for i in range(0,data_format[1]*2-(len(Buffer)-2)):
- Buffer = Buffer[0:2]+str(0)+Buffer[2:]
- # Return a list of the Byte-Frame.
- return [int(Buffer[4:6],16),int(Buffer[2:4],16)]
- # It checks the argument "data_format" for type "Long Enum" and check the range/type of "property_data", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the list of the Byte-Frame.
- # Only one Bit can be set in data_format of type "Enum".
- elif data_format==Xcom_API._format_long_enum:
- if not 0<=property_data<=2147483647 or not isinstance(property_data, int):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Long Enum\"!')
- else:
- check = False
- for i in range(0,32):
- if (2**i==2**i&property_data) and check:
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Long Enum\"!')
- elif 2**i==2**i&property_data:
- check = True
- # Define a Buffer for calculating.
- Buffer = hex(property_data)
- # Calculate the Byte-Frame.
- for i in range(0,data_format[1]*2-(len(Buffer)-2)):
- Buffer = Buffer[0:2]+str(0)+Buffer[2:]
- # Return a list of the Byte-Frame.
- return [int(Buffer[8:10],16),int(Buffer[6:8],16),int(Buffer[4:6],16),int(Buffer[2:4],16)]
- # It checks the argument "data_format" for type "INT32" and check the range/type of "property_data", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the list of the Byte-Frame.
- elif data_format==Xcom_API._format_int32:
- if not -2147483648<=property_data<=2147483647 or not isinstance(property_data, int):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"INT32\"!')
- else:
- # Calculate the Byte-Frame.
- if property_data<0:
- # Define a Buffer for calculating.
- Buffer = hex(2**32 + property_data)
- else:
- # Define a Buffer for calculating.
- Buffer = hex(property_data)
-
- for i in range(0,data_format[1]*2-(len(Buffer)-2)):
- Buffer = Buffer[0:2]+str(0)+Buffer[2:]
-
- # Return a list of the Byte-Frame.
- return [int(Buffer[8:10],16),int(Buffer[6:8],16),int(Buffer[4:6],16),int(Buffer[2:4],16)]
- # It checks the argument "data_format" for type "Float" and check the range/type of "property_data", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the list of the Byte-Frame.
- elif data_format==Xcom_API._format_float:
- if not -2147483648<=property_data<=2147483647 or not isinstance(property_data, float):
- raise ValueError('Invalid \"property_data\" for the data_format of type \"Float\"!')
- else:
- # Calculate the Byte-Frame.
- Buffer = struct.pack("!f",property_data)
- # Return a list of the Byte-Frame.
- return [Buffer[3],Buffer[2],Buffer[1],Buffer[0]]
- # It raises an Error, if the argument "data_format" doesn't fit.
- else:
- raise ValueError('data_format is unknown!')
- # This Method generate a Value of a Byte-Frame depending of the format. It returns the value as a integer/float.
-
- def __byte_frame_to_value(byte_frame, data_format):
- """
- ### Description:
- This Method generate a Value of a Byte-Frame depending of the format. It returns the value as a integer/float.
- ### Arguments:
- The **<byte_frame>** argument must be a type of **list** or **bytearray**. The lenght depends of the type of **<data_format>**.
- For the **<data_format>** argument use one of the following formats:
- +-+-+
- | | |
- +=+=+
- | _format_bool | = [1, 1] |
- +-+-+
- | _format_format | = [2, 2] |
- +-+-+
- | _format_short_int | = [3, 2] |
- +-+-+
- | _format_enum | = [4, 2] |
- +-+-+
- | _format_short_enum | = [5, 2] |
- +-+-+
- | _format_long_enum | = [6, 4] |
- +-+-+
- | _format_error | = [7, 2] |
- +-+-+
- | _format_int32 | = [8, 4] |
- +-+-+
- | _format_float | = [9, 4] |
- +-+-+
- | _format_byte | = [10, 1] |
- +-+-+
- ### Return-Value:
- This Method return a value of type **int** or **float** depending of the **<data_format>** argument.
- ### Example-Code:
- ```>>> Byte_Frame = [0x0, 0x0, 0x40, 0x41]
- >>> Value = Xcom_API.__byte_frame_to_value(Byte_Frame, Xcom_API._format_float)
- >>> Value
- 12.0
- **Or if you are not using this function inside the API:**
- ```>>> Byte_Frame = [0x0, 0x0, 0x40, 0x41]
- >>> Value = Xcom_API._Xcom_API__byte_frame_to_value(Byte_Frame, Xcom_API._format_float)
- >>> Value
- 12.0
- """
- # It checks the argument "data_format" for type "Bool" and check the length/type of "byte_frame", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it returns the value of the Byte-Frame.
- if data_format==Xcom_API._format_bool:
- if not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int) or not 0<=byte_frame[0]<=1:
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"bool\"!')
- else:
- # Return the value of the Byte-Frame.
- return byte_frame[0]
-
- # It checks the argument "data_format" for type "Byte" and check the length/type of "byte_frame", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it returns the value of the Byte-Frame.
- elif data_format==Xcom_API._format_byte:
- if not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int):
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"Byte\"!')
- else:
- # Return the value of the Byte-Frame.
- return byte_frame[0]
-
- # It checks the argument "data_format" for type "Error" and check the length/type of "byte_frame", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the value of the Byte-Frame.
- elif data_format==Xcom_API._format_error:
- if not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int) or not isinstance(byte_frame[1], int):
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"Error\"!')
- else:
- # Define a Buffer.
- Buffer = '0x'
- # Calculate the value.
- for i in range(0,data_format[1]):
- if len(hex(byte_frame[data_format[1]-1-i]))==4:
- Buffer = Buffer + hex(byte_frame[data_format[1]-1-i])[2:]
- else:
- Buffer = Buffer + '0' + hex(byte_frame[data_format[1]-1-i])[2:]
- # Return the value of the Byte-Frame.
- return int(Buffer,16)
- # It checks the argument "data_format" for type "Format" or "Short Integer" and check the length/type of "byte_frame", depending
- # of the data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the value of the Byte-Frame.
- elif data_format==Xcom_API._format_format or data_format==Xcom_API._format_short_int:
- if not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int) or not isinstance(byte_frame[1], int):
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"Format\" or \"Short Integer\"!')
- else:
- # Define a Buffer.
- Buffer = '0x'
- # Calculate the value.
- for i in range(0,data_format[1]):
- if len(hex(byte_frame[data_format[1]-1-i]))==4:
- Buffer = Buffer + hex(byte_frame[data_format[1]-1-i])[2:]
- else:
- Buffer = Buffer + '0' + hex(byte_frame[data_format[1]-1-i])[2:]
- # Return the value of the Byte-Frame.
- if int(Buffer,16)<32768:
- return int(Buffer,16)
- else:
- return (-65536 + int(Buffer,16))
- # It checks the argument "data_format" for type "Enum" or "Short Enum" and check the length/type of "byte_frame", depending of the
- # data_format. It raises an ValueError if the checks failed, otherwise it calculate and returns the value of the Byte-Frame.
- elif data_format==Xcom_API._format_enum or data_format==Xcom_API._format_short_enum:
- if not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int) or not isinstance(byte_frame[1], int):
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"Enum\" or \"Short Enum\"!')
- else:
- # Define a Buffer.
- Buffer = '0x'
- # Calculate the value.
- for i in range(0,data_format[1]):
- if len(hex(byte_frame[data_format[1]-1-i]))==4:
- Buffer = Buffer + hex(byte_frame[data_format[1]-1-i])[2:]
- else:
- Buffer = Buffer + '0' + hex(byte_frame[data_format[1]-1-i])[2:]
- # Return the value of the Byte-Frame.
- if int(Buffer,16)<32768:
- return int(Buffer,16)
- else:
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"Enum\" or \"Short Enum\"!')
-
- # It checks the argument "data_format" for type "Long Enum" and check the length/type of "byte_frame", depending of the data_format.
- # It raises an ValueError if the checks failed, otherwise it calculate and returns the value of the Byte-Frame.
- elif data_format==Xcom_API._format_long_enum:
- if (not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int) or not isinstance(byte_frame[1], int)
- or not isinstance(byte_frame[2], int) or not isinstance(byte_frame[3], int)):
- raise ValueError('Invalid \"byte_frame" for the data_format of type \"Long Enum\"!')
- else:
- # Define a Buffer.
- Buffer = '0x'
- # Calculate the value.
- for i in range(0,data_format[1]):
- if len(hex(byte_frame[data_format[1]-1-i]))==4:
- Buffer = Buffer + hex(byte_frame[data_format[1]-1-i])[2:]
- else:
- Buffer = Buffer + '0' + hex(byte_frame[data_format[1]-1-i])[2:]
- # Return the value of the Byte-Frame.
- if int(Buffer,16)<2147483648:
- return int(Buffer,16)
- else:
- raise ValueError('Invalid \"byte_frame" for the data_format of type \"Long Enum\"!')
- # It checks the argument "data_format" for type "INT32" and check the length/type of "byte_frame", depending of the data_format.
- # It raises an ValueError if the checks failed, otherwise it calculate and returns the value of the Byte-Frame.
- elif data_format==Xcom_API._format_int32:
- if (not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int) or not isinstance(byte_frame[1], int)
- or not isinstance(byte_frame[2], int) or not isinstance(byte_frame[3], int)):
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"INT32\"!')
- else:
- # Define a Buffer.
- Buffer = '0x'
- # Calculate the value.
- for i in range(0,data_format[1]):
- if len(hex(byte_frame[data_format[1]-1-i]))==4:
- Buffer = Buffer + hex(byte_frame[data_format[1]-1-i])[2:]
- else:
- Buffer = Buffer + '0' + hex(byte_frame[data_format[1]-1-i])[2:]
- # Return the value of the Byte-Frame.
- if int(Buffer,16)<2147483648:
- return int(Buffer,16)
- else:
- return (-4294967296 + int(Buffer,16))
- # It checks the argument "data_format" for type "Float" and check the length/type of "byte_frame", depending of the data_format.
- # It raises an ValueError if the checks failed, otherwise it calculate and returns the value of the Byte-Frame.
- elif data_format==Xcom_API._format_float:
- if (not len(byte_frame)==data_format[1] or not isinstance(byte_frame[0], int) or not isinstance(byte_frame[1], int)
- or not isinstance(byte_frame[2], int) or not isinstance(byte_frame[3], int)):
- raise ValueError('Invalid \"byte_frame\" for the data_format of type \"Float\"!')
- else:
- # Define a Buffer.
- Buffer = bytearray([byte_frame[3],byte_frame[2],byte_frame[1],byte_frame[0]])
- # Calculate and return the value of the Byte-Frame.
- return struct.unpack("!f",Buffer)[0]
- # It raises an Error, if the argument "format" doesn't fit.
- else:
- raise ValueError('data_format is unknown!')
-
- # This Method does a Frame-Check. It checks the startbyte, Frame-Length, the checksum and the response-flags. It returns a
- # boolean-value of the result.
- def __frame_check(self,bytearray_of_frame):
- """
- ### Description:
- This Method does a Frame-Check. It checks the startbyte, Frame-Length, the checksum and the response-flags. It returns a
- boolean-value of the result.
- ### Arguments:
- The **<self>** argument must be an object. The **<bytearray_of_frame>** argument is a complete Byte_frame.
- ### Return-Value:
- This Method return a **boolean**.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Byte_Frame = [0xAA, 0x37, 0x65, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xA, 0x0, 0xA6, 0x5E, 0x2, 0x2, 0x2, 0x0, 0x53, 0x4, 0x0, 0x0, 0x5, 0x0, 0x61, 0x3C]
- >>> Check = Xcom_API.__frame_check(Object,Byte_Frame)
- >>> Check
- True
- **Or if you are not using this function inside the API:**
- ```>>> Object = Xcom_API()
- >>> Byte_Frame = [0xAA, 0x37, 0x65, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0xA, 0x0, 0xA6, 0x5E, 0x2, 0x2, 0x2, 0x0, 0x53, 0x4, 0x0, 0x0, 0x5, 0x0, 0x61, 0x3C]
- >>> Check = Xcom_API._Xcom_API__frame_check(Object,Byte_Frame)
- >>> Check
- True
- """
-
- # Define Buffer for Frame_check.
- Buffer = list(bytearray_of_frame)
-
- try:
- # Check Start-Byte available
- if not Buffer[0]==0xAA:
- raise ValueError('Can\'t find Start-Frame (0xAA)')
- # Check checksum if activated and check Frame-Length
- if self.__crc and len(Buffer)>=14:
- # check Header-Checksum
- if not Xcom_API.__calculate_checksum(Buffer[1:12])==Buffer[12:14]:
- raise ValueError('Header-Checksum wrong!')
- # check Frame-Length
- if not len(Buffer)==(Xcom_API.__byte_frame_to_value(Buffer[10:12],Xcom_API._format_short_int) + 16):
- raise ValueError('Frame is not complete!')
- # check Data-Checksum
- if not Xcom_API.__calculate_checksum(Buffer[14:(len(Buffer)-2)])==Buffer[(len(Buffer)-2):len(Buffer)]:
- raise ValueError('Data-Checksum wrong!')
- elif not self.__crc and len(Buffer)>=14:
- # check Frame-Length
- if not len(Buffer)==(Xcom_API.__byte_frame_to_value(Buffer[10:12],Xcom_API._format_short_int) + 16):
- raise ValueError('Frame is not complete!')
- else:
- raise ValueError('Frame is not complete!')
-
- # Check Response-Flags
- if not Buffer[14]>0:
- raise ValueError('Frame is not a Response-Frame!')
- return True
-
- except IndexError:
- raise ValueError('Frame is not complete!')
-
- ##################################################################################################################################
- # Public-Methods #
- ##################################################################################################################################
- # This method is used to generate a Byte-Frame for a 'read'-instruction. It Returns a bytearray.
-
- def get_read_frame_ext(self, object_type, object_id, property_id):
- """
- ### Description:
- This method is used to generate a Byte-Frame for a 'read'-instruction. It Returns a bytearray.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<object_type>** argument indicates the type of the **<object_id>**. The following shows the possibilities:
- +-+-+
- | | |
- +=+=+
- | _object_type_info | = 1 |
- +-+-+
- | _object_type_parameter | = 2 |
- +-+-+
- | _object_type_message | = 3 |
- +-+-+
- | _object_type_datalog_field | = 5 |
- +-+-+
- | _object_type_datalog_transfer | = 257 |
- +-+-+
- The **<object_id>** argument indicates, which id should be read. You can find a list of all id's in the communication protocoll
- at http://www.studer-innotec.com/de/downloads/.
- The **<property_id>** argument indicates, which type the property_data has, which you want to read. The following shows the possibilities:
- +-+-+
- | | |
- +=+=+
- | _property_id_value | = 1 |
- +-+-+
- | _property_id_string | = 1 |
- +-+-+
- | _property_id_value_qsp | = 5 |
- +-+-+
- | _property_id_min_qsp | = 6 |
- +-+-+
- | _property_id_max_qsp | = 7 |
- +-+-+
- | _property_id_level_qsp | = 8 |
- +-+-+
- | _property_id_unsaved_value_qsp | = 13 |
- +-+-+
- | _property_id_invalid_Action | = 0 |
- +-+-+
- | _property_id_sd_start | = 21 |
- +-+-+
- | _property_id_sd_datablock | = 22 |
- +-+-+
- | _property_id_sd_ack_continue | = 23 |
- +-+-+
- | _property_id_sd_nack_retry | = 24 |
- +-+-+
- | _property_id_sd_abort | = 25 |
- +-+-+
- | _property_id_sd_finish | = 26 |
- +-+-+
- ### Return-Value:
- This Method return a **bytearray** of the frame.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> input_current = 3116
- >>> Byte_frame = Object.get_read_frame_ext(Xcom_API._object_type_info, input_current, Xcom_API._property_id_value)
- >>> Byte_frame
- bytearray(b'\\xAA\\x00\\x01\\x00\\x00\\x00\\x65\\x00\\x00\\x00\\x0A\\x00\\x6F\\x71\\x00\\x01\\x01\\x00\\x2C\\x0C\\x00\\x00\\x01\\x00\\x3A\\x4D')
- """
-
- # Create Buffer
- Buffer = []
-
- # Append Buffer with Start-Byte.
- Buffer.append(Xcom_API.__start_byte)
-
- # Append Buffer with Frame-Flags.
- Buffer.append(Xcom_API.__frame_flags)
-
- # Extend Buffer with Source-Address.
- Buffer.extend(Xcom_API.__value_to_byte_frame(self.__source,Xcom_API._format_int32))
-
- # Extend Buffer with Destination-Address.
- Buffer.extend(Xcom_API.__value_to_byte_frame(self.__dest,Xcom_API._format_int32))
-
- # Extend Buffer with Data-Length.
- Buffer.extend(Xcom_API.__value_to_byte_frame(Xcom_API.__data_frame,Xcom_API._format_short_int))
-
- # Extend Buffer with Header-Checksum.
- Buffer.extend(Xcom_API.__calculate_checksum(Buffer[1:len(Buffer)]))
-
- # Append Buffer with Data-Flags.
- Buffer.append(Xcom_API.__data_flags)
-
- # Append Buffer with Service_ID.
- Buffer.append(Xcom_API.__service_read)
-
- # Extend Buffer with Opject_Type.
- Buffer.extend(Xcom_API.__value_to_byte_frame(object_type,Xcom_API._format_short_int))
-
- # Extend Buffer with Object_ID.
- Buffer.extend(Xcom_API.__value_to_byte_frame(object_id,Xcom_API._format_int32))
-
- # Extend Buffer with Property_ID.
- Buffer.extend(Xcom_API.__value_to_byte_frame(property_id,Xcom_API._format_short_int))
-
- # Extend Buffer with Data-Checksum.
- Buffer.extend(Xcom_API.__calculate_checksum(Buffer[14:len(Buffer)]))
-
- # Return Byte-Frame.
- return bytearray(Buffer)
-
- # This method is used to generate a Byte-Frame for a 'write'-instruction. It Returns a List of Bytes.
-
- def get_write_frame_ext(self, object_type, object_id, property_id, property_data, data_format):
- """
- ### Description:
- This method is used to generate a Byte-Frame for a 'write'-instruction. It Returns a bytearray.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<object_type>** argument indicates the type of the **<object_id>**. The following shows the possibilities:
- +-+-+
- | | |
- +=+=+
- | _object_type_info | = 1 |
- +-+-+
- | _object_type_parameter | = 2 |
- +-+-+
- | _object_type_message | = 3 |
- +-+-+
- | _object_type_datalog_field | = 5 |
- +-+-+
- | _object_type_datalog_transfer | = 257 |
- +-+-+
- The **<object_id>** argument indicates, which id should be written. You can find a list of all id's in the communication protocoll
- at http://www.studer-innotec.com/de/downloads/.
- The **<property_id>** argument indicates, which type the property_data has, which you want to read. The following shows the possibilities:
- +-+-+
- | | |
- +=+=+
- | _property_id_value | = 1 |
- +-+-+
- | _property_id_string | = 1 |
- +-+-+
- | _property_id_value_qsp | = 5 |
- +-+-+
- | _property_id_min_qsp | = 6 |
- +-+-+
- | _property_id_max_qsp | = 7 |
- +-+-+
- | _property_id_level_qsp | = 8 |
- +-+-+
- | _property_id_unsaved_value_qsp | = 13 |
- +-+-+
- | _property_id_invalid_Action | = 0 |
- +-+-+
- | _property_id_sd_start | = 21 |
- +-+-+
- | _property_id_sd_datablock | = 22 |
- +-+-+
- | _property_id_sd_ack_continue | = 23 |
- +-+-+
- | _property_id_sd_nack_retry | = 24 |
- +-+-+
- | _property_id_sd_abort | = 25 |
- +-+-+
- | _property_id_sd_finish | = 26 |
- +-+-+
- The **<property_data>** argument is the value you want to send. The format depends of the **<data_format>** argument.
- For the **<data_format>** argument use one of the following formats:
- +-+-+
- | | |
- +=+=+
- | _format_bool | = [1, 1] |
- +-+-+
- | _format_format | = [2, 2] |
- +-+-+
- | _format_short_int | = [3, 2] |
- +-+-+
- | _format_enum | = [4, 2] |
- +-+-+
- | _format_short_enum | = [5, 2] |
- +-+-+
- | _format_long_enum | = [6, 4] |
- +-+-+
- | _format_error | = [7, 2] |
- +-+-+
- | _format_int32 | = [8, 4] |
- +-+-+
- | _format_float | = [9, 4] |
- +-+-+
- | _format_byte | = [10, 1] |
- +-+-+
-
- ### Return-Value:
- This Method return a **bytearray** of the frame.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Equalization_current = 1290
- >>> Data_in_Ampere = 120.0
- >>> Byte_frame = Object.get_write_frame_ext(Xcom_API._object_type_parameter, Equalization_current, Xcom_API._property_id_value, Data_in_Ampere, Xcom_API._format_float)
- >>> Byte_frame
- bytearray(b'\\xAA\\x00\\x01\\x00\\x00\\x00\\x65\\x00\\x00\\x00\\x0E\\x00\\x73\\x79\\x00\\x02\\x02\\x00\\x0A\\x05\\x00\\x00\\x01\\x00\\x00\\x00\\xF0\\x42\\x45\\xDD')
- """
-
- # Create Buffer
- Buffer = []
-
- # Append Buffer with Start-Byte.
- Buffer.append(Xcom_API.__start_byte)
-
- # Append Buffer with Frame-Flags.
- Buffer.append(Xcom_API.__frame_flags)
-
- # Extend Buffer with Source-Address.
- Buffer.extend(Xcom_API.__value_to_byte_frame(self.__source,Xcom_API._format_int32))
-
- # Extend Buffer with Destination-Address.
- Buffer.extend(Xcom_API.__value_to_byte_frame(self.__dest,Xcom_API._format_int32))
-
- # Extend Buffer with Data-Length.
- Buffer.extend(Xcom_API.__value_to_byte_frame(Xcom_API.__data_frame + data_format[1],Xcom_API._format_short_int))
-
- # Extend Buffer with Header-Checksum.
- Buffer.extend(Xcom_API.__calculate_checksum(Buffer[1:len(Buffer)]))
-
- # Append Buffer with Data-Flags.
- Buffer.append(Xcom_API.__data_flags)
-
- # Append Buffer with Service_ID.
- Buffer.append(Xcom_API.__service_write)
-
- # Extend Buffer with Opject_Type.
- Buffer.extend(Xcom_API.__value_to_byte_frame(object_type,Xcom_API._format_short_int))
-
- # Extend Buffer with Object_ID.
- Buffer.extend(Xcom_API.__value_to_byte_frame(object_id,Xcom_API._format_int32))
-
- # Extend Buffer with Property_ID.
- Buffer.extend(Xcom_API.__value_to_byte_frame(property_id,Xcom_API._format_short_int))
-
- # Extend Buffer with Property_Data.
- Buffer.extend(Xcom_API.__value_to_byte_frame(property_data,data_format))
-
- # Extend Buffer with Data-Checksum.
- Buffer.extend(Xcom_API.__calculate_checksum(Buffer[14:len(Buffer)]))
-
- # Return Byte-Frame.
- return bytearray(Buffer)
- # This method is used to decode Data from the received Byte-Frame, what you get from the xtender-system.
- # It returns a List with the result of the returned Data and the Data itself.
- def get_data_from_frame_ext(self, bytearray_of_frame, data_format):
- """
- ### Description:
- This method is used to decode Data from the received Byte-Frame, what you get from the xtender-system.
- If CRC-Check is active, it will check the byte-frame and raises a Value_Error, if a CRC-Error was detected.
- It returns a List with the result of the returned Data and the Data itself.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<bytearray_of_frame>** argument is the frame what you get, when you receive data from the serial port.
- The **<data_format>** argument is needed to decode the value. For the **<data_format>** argument use one of the following formats:
- +-+-+
- | | |
- +=+=+
- | _format_bool | = [1, 1] |
- +-+-+
- | _format_format | = [2, 2] |
- +-+-+
- | _format_short_int | = [3, 2] |
- +-+-+
- | _format_enum | = [4, 2] |
- +-+-+
- | _format_short_enum | = [5, 2] |
- +-+-+
- | _format_long_enum | = [6, 4] |
- +-+-+
- | _format_error | = [7, 2] |
- +-+-+
- | _format_int32 | = [8, 4] |
- +-+-+
- | _format_float | = [9, 4] |
- +-+-+
- | _format_byte | = [10, 1] |
- +-+-+
- ### Return-Value:
- This Method return a **list** with two elements. The First is a **boolean** value, which is **True**, if the xtender-system detects an error and the second
- element of the **list** then contains the error-id. If no error occures, then the first element is **False** und the second element contains the answer of your request.
- The returned value of the second element is a **string**, **int** or **float**, depending of the service (read/write) of the request frame and of the
- **<data_format>** argument.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Frame = bytearray(b'\\xAA\\x37\\x65\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0E\\x00\\xAA\\x66\\x02\\x01\\x02\\x00\\x53\\x04\\x00\\x00\\x05\\x00\\x00\\xD0\\x14\\x42\\x86\\x8D')
- >>> Answer = Object.get_data_from_frame_ext(Frame, Xcom_API._format_float)
- >>> Answer
- [False, 37.203125]
- """
-
- # Do a Frame-Check. If it fails, it returns a ValueError.
- if not self.__frame_check_done:
- if not Xcom_API.__frame_check(self, bytearray_of_frame):
- raise ValueError('Frame-Check failed!')
- self.__frame_check_done = False
-
- # Check Frame for an Error and return the value.
- if bytearray_of_frame[14] == 2:
- # Check if property_data available
- if len(bytearray_of_frame) == 26:
- return [False,'value_set']
- else:
- return [False, Xcom_API.__byte_frame_to_value(bytearray_of_frame[24:(24+data_format[1])],data_format)]
- else:
- return [True, Xcom_API.__byte_frame_to_value(bytearray_of_frame[24:(24+Xcom_API._format_error[1])],Xcom_API._format_error)]
- # This method is used to generate a Byte-Frame for a 'read'-instruction. It can only be used with a known Object_ID, otherwise it
- # will raise a Value_Error. It Returns a bytearray.
-
- def get_read_frame(self, object_id):
- """
- ### Description:
- This method is used to generate a Byte-Frame for a 'read'-instruction. It can only be used with a known Object_ID, otherwise it
- will raise a Value_Error. It Returns a bytearray.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<object_id>** argument indicates, which id should be read. The following shows the possibilities:
- +-+-+
- | Information-Numbers | |
- +=+=+
- | _info_battery_voltage | = 3000 |
- +-+-+
- | _info_battery_temperature | = 3001 |
- +-+-+
- | _info_battery_charge_current | = 3005 |
- +-+-+
- | _info_battery_voltage_ripple | = 3006 |
- +-+-+
- | _info_state_of_charge | = 3007 |
- +-+-+
- | _info_number_of_battery_elements | = 3050 |
- +-+-+
- | _info_input_voltage | = 3011 |
- +-+-+
- | _info_input_current | = 3012 |
- +-+-+
- | _info_input_frequency | = 3084 |
- +-+-+
- | _info_input_power | = 3138 |
- +-+-+
- | _info_output_voltage | = 3021 |
- +-+-+
- | _info_output_current | = 3022 |
- +-+-+
- | _info_output_frequency | = 3085 |
- +-+-+
- | _info_output_power | = 3139 |
- +-+-+
- | _info_operating_state | = 3028 |
- +-+-+
- | _info_boost_active | = 3019 |
- +-+-+
- | _info_state_of_inverter | = 3049 |
- +-+-+
- | _info_state_of_transfer_relay | = 3020 |
- +-+-+
- | _info_state_of_output_relay | = 3030 |
- +-+-+
- | _info_state_of_aux_relay_1 | = 3031 |
- +-+-+
- | _info_state_of_aux_relay_2 | = 3032 |
- +-+-+
- | _info_state_of_ground_relay | = 3074 |
- +-+-+
- | _info_state_of_neutral_transfer_relay | = 3075 |
- +-+-+
- | _info_state_of_remote_entry | = 3086 |
- +-+-+
-
- +-+-+
- | Parameter-Numbers | |
- +=+=+
- | _para_maximum_current_of_ac_source | = 1107 |
- +-+-+
- | _para_battery_charge_current | = 1138 |
- +-+-+
- | _para_smart_boost_allowed | = 1126 |
- +-+-+
- | _para_inverter_allowed | = 1124 |
- +-+-+
- | _para_type_of_detection_of_grid_loss | = 1552 |
- +-+-+
- | _para_charger_allowed | = 1125 |
- +-+-+
- | _para_charger_uses_only_power_from_ac | = 1646 |
- +-+-+
- | _para_ac_output_voltage | = 1286 |
- +-+-+
- | _para_inverter_frequency | = 1112 |
- +-+-+
- | _para_transfer_relay_allowed | = 1128 |
- +-+-+
- | _para_limitation_of_the_power_boost | = 1607 |
- +-+-+
- | _para_remote_entry_active | = 1545 |
- +-+-+
- ### Return-Value:
- This Method return a **bytearray** of the frame.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Byte_frame = Object.get_read_frame(Xcom_API._info_battery_voltage)
- >>> Byte_frame
- bytearray(b'\\xAA\\x00\\x01\\x00\\x00\\x00\\x65\\x00\\x00\\x00\\x0A\\x00\\x6F\\x71\\x00\\x01\\x01\\x00\\xB8\\x0B\\x00\\x00\\x01\\x00\\xC5\\x90')
- """
-
- try:
- # Read Object-ID infomations from Dictionary and store it into a Buffer.
- Buffer = Xcom_API.__para_info_dict[object_id]
-
- # Return a Byte-Frame from the Read-Extenion method.
- return self.get_read_frame_ext(Buffer[0],object_id,Buffer[1])
-
- except KeyError:
- # If the Object_ID is unknown, the method raise a ValueError.
- raise ValueError('Object_ID unknown!')
- # This method is used to generate a Byte-Frame for a 'write'-instruction. It can only be used with a known Object_ID, otherwise it
- # will raise a Value_Error. It Returns a bytearray.
-
- def get_write_frame(self, object_id, property_data):
- """
- ### Description:
- This method is used to generate a Byte-Frame for a 'write'-instruction. It can only be used with a known Object_ID, otherwise it
- will raise a Value_Error. It Returns a bytearray.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<object_id>** argument indicates, which id should be written. The following shows the possibilities:
-
- +-+-+
- | | |
- +=+=+
- | _para_maximum_current_of_ac_source | = 1107 |
- +-+-+
- | _para_battery_charge_current | = 1138 |
- +-+-+
- | _para_smart_boost_allowed | = 1126 |
- +-+-+
- | _para_inverter_allowed | = 1124 |
- +-+-+
- | _para_type_of_detection_of_grid_loss | = 1552 |
- +-+-+
- | _para_charger_allowed | = 1125 |
- +-+-+
- | _para_charger_uses_only_power_from_ac | = 1646 |
- +-+-+
- | _para_ac_output_voltage | = 1286 |
- +-+-+
- | _para_inverter_frequency | = 1112 |
- +-+-+
- | _para_transfer_relay_allowed | = 1128 |
- +-+-+
- | _para_limitation_of_the_power_boost | = 1607 |
- +-+-+
- | _para_remote_entry_active | = 1545 |
- +-+-+
- The **<property_data>** argument is the value you want to send.
- ### Return-Value:
- This Method return a **bytearray** of the frame.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Data_in_Ampere = 32.0
- >>> Byte_frame = Object.get_write_frame(Xcom_API._para_maximum_current_of_ac_source, Data_in_Ampere)
- >>> Byte_frame
- bytearray(b'\\xAA\\x00\\x01\\x00\\x00\\x00\\x65\\x00\\x00\\x00\\x0E\\x00\\x73\\x79\\x00\\x02\\x02\\x00\\x53\\x04\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x42\\xA1\\xE6')
- """
-
- try:
- # Read Object-ID infomations from Dictionary and store it into a Buffer.
- Buffer = Xcom_API.__para_info_dict[object_id]
- # Cheack for parameter
- if not Buffer[0] == Xcom_API._object_type_parameter:
- raise KeyError
- # Return a Byte-Frame from the Read-Extenion method.
- return self.get_write_frame_ext(Buffer[0],object_id,Buffer[1],property_data,Buffer[2])
-
- except KeyError:
- # If the Object_ID is unknown, the method raise a ValueError.
- raise ValueError('Object_ID unknown!')
- # This method is used to decode Data from the received Byte-Frame, what you get from the xtender-system. It can only be used with a known Object_ID,
- # otherwise it will raise a Value_Error. It returns a List with the result of the returned Data and the Data itself.
- def get_data_from_frame(self, bytearray_of_frame):
- """
- ### Description:
- This method is used to decode Data from the received Byte-Frame, what you get from the xtender-system.
- If CRC-Check is active, it will check the byte-frame and raises a Value_Error, if a CRC-Error was detected.
- It can only be used with a known Object_ID, otherwise it will raise a Value_Error. It returns a List with the result of the returned Data and the Data itself.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<bytearray_of_frame>** argument is the frame what you get, when you receive data from the serial port.
- ### Return-Value:
- This Method return a **list** with two elements. The First is a **boolean** value, which is **True**, if the xtender-system detects an error and the second
- element of the **list** then contains the error-id. If no error occures, then the first element is **False** und the second element contains the answer of your request.
- The returned value of the second element is a **string**, **int** or **float**, depending of the service (read/write) of the request frame and of the
- **<data_format>** argument.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Frame = bytearray(b'\\xAA\\x37\\x65\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0E\\x00\\xAA\\x66\\x02\\x01\\x01\\x00\\xB8\\x0B\\x00\\x00\\x01\\x00\\x00\\x40\\x42\\x42\\x8B\\x46')
- >>> Answer = Object.get_data_from_frame(Frame)
- >>> Answer
- [False, 48.5625]
- """
- try:
- # Do a Frame-Check. If it fails, it returns a ValueError.
- if Xcom_API.__frame_check(self, bytearray_of_frame):
- self.__frame_check_done = True
- else:
- raise ValueError('Frame-Check failed!')
- # Read Object-ID infomations from Dictionary and store it into a Buffer.
- Buffer = Xcom_API.__para_info_dict[Xcom_API.__byte_frame_to_value(bytearray_of_frame[18:22],Xcom_API._format_int32)]
-
- # Return a Byte-Frame from the Read-Extension method.
- return self.get_data_from_frame_ext(bytearray_of_frame,Buffer[2])
- except KeyError:
- # If the Object_ID is unknown, the method raise a ValueError.
- self.__frame_check_done = False
- raise ValueError('Object_ID unknown!')
- # This method is used to return the frame-flags as a binary.
- def get_bin_from_frame_flags(self, bytearray_of_frame):
- """
- ### Description:
- This method is used to return the frame-flags as a binary.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<bytearray_of_frame>** argument is the frame what you get, when you receive data from the serial port.
- ### Return-Value:
- The returned value is type **binary**.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Frame = bytearray(b'\\xAA\\x37\\x65\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0E\\x00\\xAA\\x66\\x02\\x01\\x01\\x00\\xB8\\x0B\\x00\\x00\\x01\\x00\\x00\\x40\\x42\\x42\\x8B\\x46')
- >>> Answer = Object.get_bin_from_frame_flags(Frame)
- >>> Answer
- 0b00110111
- """
- # Do a Frame-Check. If it fails, it returns a ValueError.
- if not Xcom_API.__frame_check(self, bytearray_of_frame):
- raise ValueError('Frame-Check failed!')
- # Create a Buffer with binary Information.
- Buffer = bin(bytearray_of_frame[1])
- # Extend Buffer to 8-bit
- for i in range(0,10-len(Buffer)):
- Buffer = Buffer[0:2] + '0' + Buffer[2:]
-
- # Return Buffer.
- return Buffer
- # This method is used to return the frame-flags as a list with explanation (string) for each bit, starting from LSB to MSB.
- def get_text_from_frame_flags(self, bytearray_of_frame):
- """
- ### Description:
- This method is used to return the frame-flags as a **list** with explanation (**string**) for each bit, starting with lsb.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<bytearray_of_frame>** argument is the frame what you get, when you receive data from the serial port.
- ### Return-Value:
- The method returns a **list** with **strings** of explanation for each bit of the frame-flags, starting from LSB to MSB.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Frame = bytearray(b'\\xAA\\x37\\x65\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0E\\x00\\xAA\\x66\\x02\\x01\\x01\\x00\\xB8\\x0B\\x00\\x00\\x01\\x00\\x00\\x40\\x42\\x42\\x8B\\x46')
- >>> Answer = Object.get_text_from_frame_flags(Frame)
- >>> Answer
- ['Messages are pending.','A reset or restart was carried out.','The SD-Card is present.','The SD-Card is not full.','New datalog file on the SD-Card.','Datalogger is supported.']
- """
- # Create Buffer and get binary from byte-frame.
- Buffer = self.get_bin_from_frame_flags(bytearray_of_frame)
-
- # Create Out-Buffer.
- BufferOut = []
- # Check bit 0.
- if int(Buffer[9]) == 1:
- BufferOut.append('Messages are pending.')
- else:
- BufferOut.append('No messages are pending.')
- # Check bit 1.
- if int(Buffer[8]) == 1:
- BufferOut.append('A reset or restart was carried out.')
- else:
- BufferOut.append('No reset or restart was carried out.')
- # Check bit 2.
- if int(Buffer[7]) == 1:
- BufferOut.append('The SD-Card is present.')
- else:
- BufferOut.append('No SD-Card is present')
- # Check bit 3.
- if int(Buffer[6]) == 1:
- BufferOut.append('The SD-Card is full.')
- else:
- BufferOut.append('The SD-Card is not full.')
- # Check bit 4.
- if int(Buffer[5]) == 1:
- BufferOut.append('New datalog file on the SD-Card.')
- else:
- BufferOut.append('No new datalog file on the SD-Card.')
- # Check bit 5.
- if int(Buffer[4]) == 1:
- BufferOut.append('Datalogger is supported.')
- else:
- BufferOut.append('Datalogger is not supported.')
- # Return list with Frame-flag informations.
- return BufferOut
- # This method is used to get the error message from the error-id.
- def get_text_from_error_id(self, error_id):
- """
- ### Description:
- This method is used to get the error message from the error-id.
- ### Arguments:
- The **<self>** argument is pointing to the object, which calls the method.
- The **<error_id>** argument is an **int** from the xtender-system.
- ### Return-Value:
- The method returns a **strings** with the explanation of the error-id.
- ### Example-Code:
- ```>>> Object = Xcom_API()
- >>> Error_ID = 0x0022
- >>> Answer = Object.get_text_from_error_id(Error_ID)
- >>> Answer
- 'OBJECT_ID_NOT_FOUND'
- """
-
- try:
- # Check ID and store error-message in Buffer
- Buffer = Xcom_API.__error_code_dict[error_id]
- # return error-message
- return Buffer
- except KeyError:
- # If Error ID is unknown
- return 'Error-ID is unknown.'
|