1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729 |
- #!/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
- ##################################################################################################################################
- # 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
- ##################################################################################################################################
- # 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]}
- ##################################################################################################################################
- # 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.'
|