[![](https://gogs.es-lab.de/attachments/5a362329-e45e-40d0-a018-b7ddafd296f9)](https://www.hs-anhalt.de/startseite.html)
# <p>&#x1F5C3; Xcom-API</p>
[![]( https://img.shields.io/badge/version-v1.0-red.svg?style=plain )](https://gogs.es-lab.de/mueller_to/Xcom-API) [![]( https://img.shields.io/badge/python-3.4,_3.5,_3.6-green.svg?style=plain )](https://www.python.org/) [![]( https://img.shields.io/badge/license-GNU%20GPL%20v3-blue.svg?style=plain )](https://gogs.es-lab.de/mueller_to/Xcom-API/src/master/LICENSE) [![]( https://img.shields.io/badge/documentation-wiki-yellow.svg?style=plain)](https://gogs.es-lab.de/mueller_to/Xcom-API/wiki) [![]( https://img.shields.io/badge/download-zip-orange.svg?style=plain)](https://gogs.es-lab.de/mueller_to/Xcom-API/archive/master.zip)
<br><br>

## <p>&#x1F4DC; Table of Contents</p>

* [Introduction](#introduction)
* [Xcom-API-Class](#xcom-api-class)
    * [Create and Delete an Object](#create-and-delete-an-object)
    * [Class-Attributes](#class-attributes)
    * [Information-Methods](#information-methods)
        * [get_source_address](#get_source_address)
        * [get_destination_address](#get_destination_address)
        * [is_crc_check_active](#is_crc_check_active)
        * [get_object_counter](#get_object_counter)
        * [get_prog_name](#get_prog_name)
        * [get_prog_version](#get_prog_version)
    * [Public-Class-Methods](#public-class-methods)
        * [get_read_frame](#get_read_frame)
        * [get_read_frame_ext](#get_read_frame_ext)
        * [get_write_frame](#get_write_frame)
        * [get_write_frame_ext](#get_write_frame_ext)
        * [get_data_from_frame](#get_data_from_frame)
        * [get_data_from_frame_ext](#get_data_from_frame_ext)
        * [get_bin_from_frame_flags](#get_bin_from_frame_flags)
        * [get_text_from_frame_flags](#get_text_from_frame_flags)
        * [get_text_from_error_id](#get_text_from_error_id)
* [Hardware Setup](#hardware-setup)
    * [Hardware Information](#hardware-information)
    * [Xcom-232i-Setup](#xcom-232i-setup)
    * [Raspberry Pi Setup](#raspberry-pi-setup)
        * [Copy Image to a SD-Card](#copy-image-to-a-sd-card)
        * [Create your own Image](#create-your-own-image)
* [Test-Program](#test-program)
    * [Run Test-Program](#run-test-program)
    * [Xcom-Test-Loop-Program](#xcom-test-loop-program)
    * [Xcom-Test-Program](#xcom-test-program)
* [References](#references)

---

<div id="introduction">

## <p>&#x2139; Introduction</p>
Welcome to the Wiki of the Xcom-API. This project is about an API (**A**pplication **P**rogramming **I**nterface) designed as a python-class, which is used to encode and decode byte-frames for communication between a Xtender-System and a PC, especially a Raspberry Pi with a Raspicomm extension module. The class also contains methods for error and frame-flag decoding and methods to get object or class informations.

>**Note:** The API and the Test-Program was created with Microsoft's integrated development environment (IDE) Visual Studio Code (VSC). This is an Open-Source IDE from Microsoft for many different programming-languages for Windows, Linux and Mac with an easy to use git integration. So you can easily add this project to VSC by cloning this Git-Repository. Of course you can open the python-files with other IDE's you prefer too.
>
>#### <p>&#x2601; Git-Repository-Link: https://gogs.es-lab.de/mueller_to/Xcom-API </p>

On the following pages you will find many informations about the usage of the API such like: An explanation of the methods of the API and how to invoke these methods inside a python-script. 

Furthermore there are test-programs called "Xcom-Test-Program" and "Xcom-Test-Loop-Program", which you can use for testing the Xcom-API and where you get some impressions of how to use the Xcom-API. There are also explanation for how to use these test-programs. This concerns the hardware and software setup of the Raspberry Pi, if you won't use the given Raspberry Pi image.

<div id="xcom-api-class">

## <br><p>&#x1F5C3; Xcom-API-Class</p>
This class is used to encode byte-frames, which are needed to communicate with Xtender-Modules over the RS232-BUS with the help of the Xcom-232i. After encoding the byte-frame, you can use the module "pyserial" to communicate with the Serial-BUS and to put the byte-frame into the write-method of "pyserial". You can also decode read-frames of the Serial-BUS with this class. 

The 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 encode byte-frames with other parameter- and information-numbers too, that you can find in the documentation of the Xcom-232i. The class also contains methods for error and frame-flag decoding and methods to get object or class informations

>**Note:** The link to the documentation of the Xcom-232i can you find under the section: [Hardware Information](#hardware-information).

On the following sections, there will be describe the [Information-Methods](#information-methods), [Public-Class-Methods](#public-class-methods), [Class-Attributes](#class-attributes) and how to [create and delete an object](#create-and-delete-an-object).

### Create and Delete an Object
##### Import Xcom-API-Class:
To use the Xcom-API, either you need to import the class into your python-script, or you write your code directly inside the "*Xcom_API.py*" file. If you want to import the "*Xcom_API.py*" into your own python script, make sure, that the "*Xcom_API.py*" file is located inside the python-module search path. This is either the folder/directory where your script is located or under Microsoft Windows the path:
```text
<drive>:\<install_path_to_python>\<python_folder_with_version>\Lib\site-packages
```
for example:
```text
C:\Program Files\Python34-64\Lib\site-packages
```
or under Linux the path:
```text
/usr/local/lib/<python_folder_with_version>
```
for example:
```text
/usr/local/lib/python3.4
```
To import the class use the python-code:
```python
>>> # import module
>>> from Xcom_API import Xcom_API
```
or:
```python
>>> # import module
>>> from Xcom_API import *
```
##### Create an Object:
Now you are able to create an object of the Xcom-API-Class. For example with the code:
```python
>>> # create object of the Xcom-API-Class
>>> object = Xcom_API()
```
If you create an object, the "*\_\_init\_\_*" method of the class will be called. It checks the passed arguments and store them. There are predefined arguments for this object, if you generate an objects without the relevant arguments, such like in the shown code-example before. The predefined arguments are:
```python
crc         = True
source      = 1
destination = 101
```
The "*crc*" value indicates, whether the CRC check for this object in active or not. The "*source*" value indicates the address of the Xcom-232i, which is the CAN-RS232-Bridge. Normally the standard address is "*1*", if you have only one Xcom-232i in your configuration. The "*destination*" value is the address of the Xtender-Module, which you want to communicate with. If you want to change one or more of these arguments, then change it's value. For example:
```python
>>> # create object of the Xcom-API-Class with CRC-Check disable and
>>> # destination address = 103
>>> object = Xcom_API(crc=False,destination=103)
```
For each Xtender-Module you want to communicate with, you must create an own object for it. You can't change any arguments after creating an object. This is a safety aspect, which prevents you against confusing code, because each object represents a Xtender-Module. So make sure, that the object name is well chosen. 

##### Delete an Object:
To delete an object, just use the "*del*" expression.
```python
>>> # delete an object
>>> del object
```
This calls the "\_\_del\_\_" method of the class, which delete the object specific arguments such like: "crc", "sourc

### Class-Attributes
Class-Attributes are protected values, which are marked through an underscore "_" at the beginning of the Attribute name. Protected means, that these attributes can be read out und used as an input parameter for methods, but their value must not be changed. Otherwise the Xcom-API-Class will not work correctly.

You can use/read out an attribute with the command:
```python
>>> Xcom_API.<name_of_attribute>
```
for example:
```python
>>> # Read out the number of an Info-Object_ID 
>>> Xcom_API._info_battery_voltage
    3000
```
##### Object_Type
```python
_object_type_info                     = 1
_object_type_parameter                = 2
_object_type_message                  = 3
_object_type_datalog_field            = 5
_object_type_datalog_transfer         = 257
```
##### Info-Object_ID
```python
_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-Object_ID
```python
_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
```
##### Property_ID
```python
_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
```
##### Format
```python
_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]
```

### Information-Methods
The information methods provide the user with the opportunity to inform about the current object properties and class information. The following methods can be used:
* [get_source_address](#get_source_address)
* [get_destination_address](#get_destination_address)
* [is_crc_check_active](#is_crc_check_active)
* [get_object_counter](#get_object_counter)
* [get_prog_name](#get_prog_name)
* [get_prog_version](#get_prog_version)

<div id="get_source_address">

#### get_source_address
##### Definition
```python
def get_source_address(self):
```
##### Description
The "*get_source_address*" method is used to check the source address of an object. It returns an integer value with it's source address.
##### Arguments
The "*self*" argument is pointing to the object, which calls the method.
##### Return Value
Type -> integer
##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # call the Method 'get_source_address'
>>> Src_Addr = Object.get_source_address()
>>> 
>>> # print Src_Addr
>>> print(Src_Addr)
    1
```

<div id="get_destination_address">

#### get_destination_address
##### Definition
```python
def get_destination_address(self):
```
##### Description
The "*get_destination_address*" method is used to check the destination address of an object. It returns an integer value with it's destination address.
##### Arguments
The "*self*" argument is pointing to the object, which calls the method.
##### Return Value
Type -> integer
##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # call the Method 'get_destination_address'
>>> Dest_Addr = Object.get_destination_address()
>>> 
>>> # print Dest_Addr
>>> print(Dest_Addr)
    101
```

<div id="is_crc_check_active">

#### is_crc_check_active
##### Definition
```python
def is_crc_check_active(self):
```
##### Description
The "*is_crc_check_active*" method is used to check whether the CRC-Check is activated or not. It returns a boolean value with the status of the CRC-Check. If CRC-Check is "*False*", the [get_data_from_frame](#get_data_from_frame), [get_data_from_frame_ext](#get_data_from_frame_ext) and [get_bin_from_frame_flags](#get_bin_from_frame_flags) methods will not do an CRC-Check before the frame will be decoded. 
##### Arguments
The "*self*" argument is pointing to the object, which calls the method.
##### Return Value
Type -> boolean
##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # call the Method 'is_crc_check_active'
>>> CRC_Active = Object.is_crc_check_active()
>>> 
>>> # print CRC_Active
>>> print(CRC_Active)
    True
```

<div id="get_object_counter">

#### get_object_counter
##### Definition
```python
def get_object_counter():
```
##### Description
The "*get_object_counter*" method is used to check the number of objects. It returns an integer value of the counter. This method can be called with and without a created object.
##### Arguments
None
##### Return Value
Type -> integer
##### Example Code
```python
>>> # call the Method 'get_object_counter'
>>> Obj_Count = Xcom_API.get_object_counter()
>>> 
>>> # print Obj_Count
>>> print(Obj_Count)
    0
>>> 
>>> # create an object of the Xcom-API-Class
>>> Object1 = Xcom_API(destination=102)
>>> 
>>> # call the Method 'get_object_counter'
>>> Obj_Count = Object1.get_object_counter()
>>> 
>>> # print Obj_Count
>>> print(Obj_Count)
    1
>>> 
>>> # create another object of the Xcom-API-Class
>>> Object2 = Xcom_API(destination=103)
>>> 
>>> # call the Method 'get_object_counter'
>>> Obj_Count = Xcom_API.get_object_counter()
>>> 
>>> # print Obj_Count
>>> print(Obj_Count)
    2
>>> 
>>> # delete objects
>>> del Object1
>>> del Object2
>>> 
>>> # call the Method 'get_object_counter'
>>> Obj_Count = Xcom_API.get_object_counter()
>>> 
>>> # print Obj_Count
>>> print(Obj_Count)
    0
```

<div id="get_prog_name">

#### get_prog_name
##### Definition
```python
def get_prog_name():
```
##### Description
The "*get_prog_name*" method is used to return the API name. This method can be called with and without a created object.
##### Arguments
None
##### Return Value
Type -> string
##### Example Code
```python
>>> # call the Method 'get_prog_name'
>>> Obj_Name = Xcom_API.get_prog_name()
>>> 
>>> # print Obj_Name
>>> print(Obj_Name)
    'Xcom_API'
>>> 
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # call the Method 'get_prog_name'
>>> Obj_Name = Object.get_prog_name()
>>> 
>>> # print Obj_Name
>>> print(Obj_Name)
    'Xcom_API'
```

<div id="get_prog_version">

#### get_prog_version
##### Definition
```python
def get_prog_version():
```
##### Description
The "*get_prog_version*" method is used to return the version of the API. This method can be called with and without a created object.
##### Arguments
None
##### Return Value
Type -> string
##### Example Code
```python
>>> # call the Method 'get_prog_version
>>> Obj_Version = Xcom_API.get_prog_version()
>>> 
>>> # print Obj_Version
>>> print(Obj_Version)
    'v1.0'
>>> 
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # call the Method 'get_prog_version'
>>> Obj_Version = Object.get_prog_version()
>>> 
>>> # print Obj_Version
>>> print(Obj_Version)
    'v1.0'
```

### Public-Class-Methods
The Public-Class-Methods are used to encode and decode byte-frames. There are also Private-Class-Methods of the API, but they are only used inside the API for internal instructions and they are not available for the user. So the Private-Class-Methods  will not be further described. The Public-Class-Methods are:
* [get_read_frame](#get_read_frame)
* [get_read_frame_ext](#get_read_frame_ext)
* [get_write_frame](#get_write_frame)
* [get_write_frame_ext](#get_write_frame_ext)
* [get_data_from_frame](#get_data_from_frame)
* [get_data_from_frame_ext](#get_data_from_frame_ext)
* [get_bin_from_frame_flags](#get_bin_from_frame_flags)
* [get_text_from_frame_flags](#get_text_from_frame_flags)
* [get_text_from_error_id](#get_text_from_error_id)

There are Methods either to encode 'read' or 'write' byte-frames and there are Methods to decode byte-frames. Furthermore there are also Methods to decode frame-flags and error-id as well. 

The non extended methods, these are methods without an '_ext' expression inside the method names, can only be used with a known Object_ID, which are listed in the section [Class-Attributes](#class-attributes). These known Object_IDs contains info and parameter numbers, which are often used. So you can easily encode and decode byte-frames without the need to know of the background informations of the byte-frame structure.

If you want to encode and decode byte-frames with other Object-IDs, you must used the extended methods. To use these Methods, you need background informations of the byte-frame structure, wich are well explained in the technical documentation of the Xcom-232i. Otherwise the Xtender-System will possibly not understand the byte-frame and will send you an error. 
>**Note:** The link to the documentation of the Xcom-232i can you find under the section: [Hardware Information](#hardware-information).

<div id="get_read_frame">

#### get_read_frame
##### Definition
```python
def get_read_frame(self, object_id):
```
##### Description
The "*get_read_frame*" method is used to encode 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 of the frame.

##### Arguments
The "*self*" argument is pointing to the object, which calls the method.

The "*object_id*" is an info or parameter number, which you want to read out.

Info-Object_ID:
```python
_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-Object_ID:
```python
_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
Type -> bytearray

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # call the Method 'get_read_frame'
>>> Byte_Frame = Object.get_read_frame(Xcom_API._info_battery_voltage)
>>> 
>>> # print Byte_Frame
>>> print(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')
```

<div id="get_read_frame_ext">

#### get_read_frame_ext
##### Definition
```python
def get_read_frame_ext(self, object_type, object_id, property_id):
```
##### Description
The "*get_read_frame_ext*" method is used to encode a byte-frame for a 'read'-instruction with other Object_IDs listed in the technical documentation of the Xcom-232i. It returns a bytearray of the frame.
>**Note:** The link to the documentation of the Xcom-232i can you find under the section: [Hardware Information](#hardware-information).

##### Arguments
The "*self*" argument is pointing to the object, which calls the method.

The "*object_type*" indicates the type of the "*object_id*", whether it is for example an info or a parameter number.

Object_Type:
```python
_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*" is an info or parameter number, which you want to read out.

The "*property_id*" identifies the property of the data, which should be read out.

Property_ID:
```python
_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
Type -> bytearray

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # set an Object_ID, which should be read out
>>> input_current = 3116
>>> 
>>> # call the Method 'get_read_frame_ext'
>>> Byte_Frame = Object.get_read_frame_ext(Xcom_API._object_type_info, input_current, Xcom_API._property_id_value)
>>> 
>>> # print Byte_Frame
>>> print(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')
```

<div id="get_write_frame">

#### get_write_frame
##### Definition
```python
def get_write_frame(self, object_id, property_data):
```
##### Description
The "*get_write_frame*" method is used to encode 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 of the frame.

##### Arguments
The "*self*" argument is pointing to the object, which calls the method.

The "*object_id*" is a parameter number, whose value you want to change.

Parameter-Object_ID:
```python
_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*" is the value, you want to send.

##### Return Value
Type -> bytearray

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # create a variable with a value for the Property_Data
>>> Data_in_Ampere = 32.0
>>> 
>>> # call the Method 'get_write_frame'
>>> Byte_Frame = Object.get_write_frame(Xcom_API._para_maximum_current_of_ac_source, Data_in_Ampere)
>>> 
>>> # print Byte_Frame
>>> print(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')
```

<div id="get_write_frame_ext">

#### get_write_frame_ext
##### Definition
```python
def get_write_frame_ext(self, object_type, object_id, property_id, property_data, data_format):
```
##### Description
The "*get_write_frame_ext*" method is used to encode a byte-frame for a 'write'-instruction with other Object_IDs listed in the technical documentation of the Xcom-232i. It returns a bytearray of the frame.
>**Note:** The link to the documentation of the Xcom-232i can you find under the section: [Hardware Information](#hardware-information).

##### Arguments
The "*self*" argument is pointing to the object, which calls the method.

The "*object_type*" indicates the type of the "*object_id*", whether it is for example an info or a parameter number.

Object_Type:
```python
_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*" is a parameter number, whose value you want to change.

The "*property_id*" identifies the property of the data, which should be change.

Property_ID:
```python
_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*" is the value, you want to send.

The "*data_format*" described the format of the "*property_data*".

Format:
```python
_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
Type -> bytearray

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # set an Object_ID, whose value should be change
>>> Equalization_current = 1290
>>> 
>>> # create a variable with a value for the Property_Data
>>> Data_in_Ampere = 120.0
>>> 
>>> # call the Method 'get_write_frame_ext'
>>> 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)
>>> 
>>> # print Byte_Frame
>>> print(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')
```

<div id="get_data_from_frame">

#### get_data_from_frame
##### Definition
```python
def get_data_from_frame(self, bytearray_of_frame):
```
##### Description
The "*get_data_from_frame*" 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. 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, integer or float, depending of the service (read/write) of the request frame and of the format of the received Property_Data.

##### 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
Type -> list

list[0]: Type -> boolean

list[1]: Type -> depending of the service (read/write) of the request frame and of the format of the received Property_Data

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # create a variable with a received frame
>>> 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')
>>> 
>>> # call the Method 'get_data_from_frame'
>>> Answer = Object.get_data_from_frame(Frame)
>>> 
>>> # print Answer
>>> print(Answer)
    (False, 48.5625)
```

<div id="get_data_from_frame_ext">

#### get_data_from_frame_ext
##### Definition
```python
def get_data_from_frame_ext(self, bytearray_of_frame, data_format):
```
##### Description
The "*get_data_from_frame_ext*" 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. 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, integer or float, depending of the service (read/write) of the request frame and of the format of the received Property_Data.

##### 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*" described the format of the received Property_Data.

Format:
```python
_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
Type -> list

list[0]: Type -> boolean

list[1]: Type -> depending of the service (read/write) of the request frame and of the format of the received Property_Data

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # create a variable with a received frame
>>> 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')
>>> 
>>> # call the Method 'get_data_from_frame_ext'
>>> Answer = Object.get_data_from_frame_ext(Frame, Xcom_API._format_float)
>>> 
>>> # print Answer
>>> print(Answer)
    (False, 37.203125)
```

<div id="get_bin_from_frame_flags">

#### get_bin_from_frame_flags
##### Definition
```python
def get_bin_from_frame_flags(self, bytearray_of_frame):
```
##### Description
The "*get_bin_from_frame_flags*" method is used to return the frame-flags as a binary. If CRC-Check is active, it will check the byte-frame and raises a Value_Error, if a CRC-Error was detected.

##### 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
Type -> string(binary)

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # create a variable with a received frame
>>> 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')
>>> 
>>> # call the Method 'get_bin_from_frame_flags'
>>> Answer = Object.get_bin_from_frame_flags(Frame)
>>> 
>>> # print Answer
>>> print(Answer)
    '0b00110111'
```

<div id="get_text_from_frame_flags">

#### get_text_from_frame_flags
##### Definition
```python
def get_text_from_frame_flags(self, bytearray_of_frame):
```
##### Description
The "*get_text_from_frame_flags*" method is used to return the frame-flags as a list with explanation (string) for each bit, starting with lsb. If CRC-Check is active, it will check the byte-frame and raises a Value_Error, if a CRC-Error was detected.

##### 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
Type -> list

list[0:5]: Type -> string

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # create a variable with a received frame
>>> 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')
>>> 
>>> # call the Method 'get_text_from_frame_flags'
>>> Answer = Object.get_text_from_frame_flags(Frame)
>>> 
>>> # print Answer
>>> print(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.')
```

<div id="get_text_from_error_id">

#### get_text_from_error_id
##### Definition
```python
def get_text_from_error_id(self, error_id):
```
##### Description
The "*get_text_from_error_id*" 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 integer value send from the Xtender-system.

##### Return Value
Type -> string

##### Example Code
```python
>>> # create an object of the Xcom-API-Class
>>> Object = Xcom_API()
>>> 
>>> # create a variable with an Error_ID
>>> Error_ID =  0x0022
>>> 
>>> # call the Method 'get_text_from_error_id'
>>> Answer = Object.get_text_from_error_id(Error_ID)
>>> 
>>> # print Answer
>>> print(Answer)
    'OBJECT_ID_NOT_FOUND'
```

<div id="hardware-setup">

## <br><p>&#x1F4BB; Hardware Setup</p>
This section explains the hardware configuration, which is necessary to use the test-programs. The test-programs were designed especially for using a Raspberry Pi with the RaspiComm module. Of course the Xcom-API-Class itself can be used in own programs with other distributions and plattforms, which can run python code. The chart below shows the connection of the hardware.

<a href="https://yuml.me/edit/cdb71477" target="_blank"><img src="https://gogs.es-lab.de/attachments/f121d125-dff9-4564-ae72-e85f82777cd9" /></a>

The Raspberry Pi is used to execute the test-program and with the help of the RaspiComm module is a RS232 connection to the Xcom-232i ensue. The Xcom-232i is a bridge betwenn the RS232 serial-Bus and the CAN-BUS, which handles the communication between the Xtender-System.

In the following sections you will get hardware-information and setup descriptions for the Raspberry Pi and the Xcom-232i.

### Hardware Information
The following table shows the needed hardware components and their usage and give you links to the product information and documentation. These components are necessary if you want to use the Xcom-Test-Program and Xcom-Test-Loop-Program.

| Component | Function | Product Information | Documentation |
|:----|:----|:----:|:----:|
| Raspberry Pi 3 | single board computer, on which is running the program | [<p>&#x1F517;</p>](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/) | [<p>&#x1F517;</p>](https://www.raspberrypi.org/documentation/) |
| RasPiComm | expansion board for the Raspberry Pi, which provides a RS232-Port over the GPIOs (UART) of the Raspberry Pi | Product is EOL | Product is EOL |
| Xcom-232i | CAN to RS232 Bridge, which is used to communicate with the Xtender-Modules | [<p>&#x1F517;</p>](https://www.studer-innotec.com/en/accessoires/xtender-series/communication-module-xcom-232i-770) | [<p>&#x1F517;</p>](https://www.studer-innotec.com/media/document/0/studer-manuel-xcom-232i-v1.3.0_en.pdf) [<p>&#x1F517;</p>](https://www.studer-innotec.com/media/document/0/technical-specification-xtender-serial-protocol-v1.6.24.zip) |
| RCC-02 | remote control and programming unit for displaying the status informations and to program parameters of the Xtender-Modules  | [<p>&#x1F517;</p>](https://www.studer-innotec.com/en/accessoires/xtender-series/rcc-02-remote-control-and-programming-centre-767) | [<p>&#x1F517;</p>](https://www.studer-innotec.com/media/document/0/manuel-rcc-v4.6.0_en.pdf) |
| Xtender-Series| is used as Battery charger and as DC to AC converter and to supply electrical power | [<p>&#x1F517;</p>](https://www.studer-innotec.com/en/products/xtender-series/) | [<p>&#x1F517;</p>](https://www.studer-innotec.com/media/document/0/manuel-xtender-v4.7.0_en-1.pdf) 

### Xcom-232i-Setup
The Xcom-232i is a bridge for the RS232-BUS to the CAN-BUS. The test-programms for the Xcom-API-Class will ask you for the baudrate. So it is essential, that you know the baudrate of the Xcom-232i, otherwise the communication between the Raspberry Pi and the Xcom-232i will fails. The standard baudrate for the RS232-BUS is 38400, but you are able to change this value to 115200. To do that you need the Xcom-Configurator, which is only available for a windows operating system.
> **Download-Link Xcom-Configurator:** [https://www.studer-innotec.com/media/document/0/xcomconfiguratorsetup_1.0.26.0.zip](https://www.studer-innotec.com/media/document/0/xcomconfiguratorsetup_1.0.26.0.zip)

The picture below shows the Xcom-Configurator program.

<center><img src=
"https://gogs.es-lab.de/attachments/e9025954-b549-4ea3-817c-f1aeacf68b5e"></center>

After downloading and installing the Xcom-Configurator, you are able to change the baudrate:
* Remove the Micro-SD-card from the Xcom-232i and insert it into your PC.

* Start the Xcom-Configurator. 

* Choose the SD-Card-Drive, where the SD-Card of Xcom-232i is located.

* Choose a Xcom-Mode, which is either "*232i (38400 bps)*" or "*232i (115200 bps)*".

* Finally click on the "*Generate*" button and a new configuration-file will be 
stored on the SD-Card.
* Remove the SD-Card from the PC and insert it into the Xcom-232i.

* The LED of the Xcom-232i should be now blinking red. This indicates, that the Xcom-232i is updating. The update is finish, when the LED is blinking green. The baudrate of the Xcom-232i is now set.

>**Note:** More Informations about the LED-state can you find in the documentation of the Xcom-232i under the section: [Hardware Information](#hardware-information).

### Raspberry Pi Setup
This section describes how to setup your Raspberry Pi, so that you are able to execute the test-programs. There are two ways possible: either you use the given Raspberry Pi image-file, which is ready to use, or you configure your own Raspberry Pi distribution/image.

<div id='copy-image-to-a-sd-card'/>

#### Copy Image to a SD-Card
This section describes how to copy the given Raspberry PI image-file to a SD-card. There is a [Linux](#linux) and a [Windows](#windows) instruction available.
> **Download-Link Raspberry Pi Image-File:** [https://gogs.es-lab.de/mueller_to/Xcom-API/src/master/Raspberry-Pi-Image](https://gogs.es-lab.de/mueller_to/Xcom-API/src/master/Raspberry-Pi-Image)

<div id='linux'/>

##### Linux Instruction 
After downloading you need to unzip the image-file first, which can be done for example with the bash-command:
```bash
unzip Raspberry_Pi_Image.zip -d <destination_folder>
```

If "*unzip*" is not installed, you can install it with the bash-command: 
```bash
sudo apt-get install unzip
```

Copying the image-file to a SD-Card will be done with the ```dd``` command. 
> **Note:** Use of the ```dd``` tool can overwrite any partition of your machine. If you specify the wrong device in the instructions below, you could delete your primary Linux partition. Please be careful.

* Insert a SD-Card into your computer with at least 8 GB storage capacity.
* Run the bash-command:
 ```
 bash df -h
 ``` 

* The left column of the results from ```df -h``` command gives the device name of your SD card. It will be listed as something like ```/dev/mmcblk0p1``` or ```/dev/sdX1```, where "*X*" is a lower case letter indicating the device. The last part (p1 or 1 respectively) is the partition number. You want to write to the whole SD card, not just one partition. You therefore need to remove that section from the name. You should see something like ```/dev/mmcblk0``` or ```/dev/sdX``` as the device name for the whole SD card. Note that the SD card can show up more than once in the output of ```df```. It will do this if you have previously written a Raspberry Pi image to this SD card, because the Raspberry Pi SD images have more than one partition.

* Now you have noted the device name, you need to unmount it so that files can't be read or written to the SD card while you are copying over the SD image. So run the bash-command ```umount /dev/sdX1```, replacing ```sdX1``` with whatever your SD card's device name is, including the partition number. If your SD card shows up more than once in the output of ```df```, this shows that the card has multiple partitions. You should unmount all of these partitions.
* Now in a terminal window, write the image to the card with the command below, making sure you replace the input file ```if=``` argument with the path to your ```img``` file, and the ```/dev/sdX``` in the output file ```of=``` argument with the correct device name. This is very important, as you will lose all the data on the hard drive if you provide the wrong device name. Make sure the device name is the name of the whole SD card as described above, not just a partition. For example: ```sdd```, not ```sdds1``` or ```sddp1```, and ```mmcblk0```, not ```mmcblk0p1```.

```bash
dd bs=4M if=Raspberry_Pi_Image.img of=/dev/mmcblk0 conv=fsync
```

> **Note:** The block size set to ```4M``` will work most of the time. If not, try ```1M```, although this will take considerably longer. Also note that if you are not logged in as root you will need to prefix this with ```sudo```.</p>

* After copying the image-file to the SD-Card, you can insert the SD-Card to your Raspberry Pi and boot it up [**[1](#references)**].

<p>Login-informations:<br>
&nbsp;&nbsp; Username: pi<br>
&nbsp;&nbsp; Password: iotraspi</p>

The test-programs can you find under `/home/pi/pythonapps`.

> **Note:** DHCP for the ethernet port of the Raspberry Pi has been disabled. The static ip-address is: 192.168.137.2. You can change this by opening the file `/etc/dhcpcd.conf` with an editor like "*nano*" and with admin privilege.

<div id='windows'/>

##### Windows Instruction 
After downloading the image-file, you can unzip the archive with windows itself or with a third party tool like "*7-ZIP*".
> **Download-Link 7-ZIP:** [http://www.7-zip.de/](http://www.7-zip.de/)

Now you need a tool called "*Win32DiskImager*" to copy the image-file to a SD-Card.

> **Download-Link Win32DiskImager:** [https://sourceforge.net/projects/win32diskimager/](https://sourceforge.net/projects/win32diskimager/)

The picture below shows the "*Win32DiskImager*".

<center><img src=https://gogs.es-lab.de/attachments/dd22ade2-5de2-4ba9-9a8a-c77b7f9193fa></center>

* Insert a SD-Card into your computer with at least 8 GB storage capacity.

* In "*Win32DiskImager*" choose the image-file and the drive of your SD-Card.

* Click on the button write (at the picture the german word "*schreiben*")  to copy the image-file to the SD-Card.

* After copying the image-file to the SD-Card, you can insert the SD-Card to your Raspberry Pi and boot it up 

<p>Login-informations:<br>
&nbsp;&nbsp; Username: pi<br>
&nbsp;&nbsp; Password: iotraspi</p>

The test-programs can you find under `/home/pi/pythonapps`.

> **Note:** DHCP for the ethernet port of the Raspberry Pi has been disabled. The static ip-address is: 192.168.137.2. You can change this by opening the file `/etc/dhcpcd.conf` with an editor like "*nano*" and with admin privilege.

<div id='create-your-own-image'/>

#### Create your own Image
Sometimes it is necessary, that you create your own image-file. For Example: If you want to use a newer or another Raspberry Pi Linux-Version as the given Raspberry Pi image-file. To do so, you need to do some configurations at the fresh installation of the Raspberry Pi operating system. The first step is to download your favorite Linux operating system for the Raspberry Pi and to install the image file to a SD-Card. This is the same procedure, which was explained in section: [Copy Image to a SD-Card](#copy-image-to-a-sd-card).
> **Note:** Other Linux operating systems especially for the Raspberry Pi can you find under: https://www.raspberrypi.org/downloads/

To setup your own raspberry pi image-file is classified into the following steps:
* [Raspberry Pi Config](#raspberry-pi-config)
* [Activate UART](#activate-uart) (Raspberry Pi 3 only)
* [Install Python-Packages](#install-python-packages)
* [Activate PiGPIO-Daemon](#activate-pigpio-daemon)

After completing the setup of your Raspberry Pi Image you can download the API and the test-programs from the repository and test it.

<div id='raspberry-pi-config'/>

##### Raspberry Pi Config
After booting up your Raspberry Pi you need to activate the serial port. If you want to communicate with the Pi over ethernet, you also need to activate SSH. To do so, run the bash-command:

```bash
sudo raspi-config
```

The picture below shows the ```raspi-config```.

![](https://gogs.es-lab.de/attachments/4e8f88cf-e5df-4ab7-8759-2a4ffe8ab2c5)

Under the category "*Interfacing-Options*" you can activate SSH and the serial-port. If you want, you can also do changes at the localization, hostname, etc. or you can activate other interfaces you need [**[2](#references)**].

<div id='activate-uart'/>

##### Activate UART
> **Note:** This step is only necessary, if you use a Raspberry Pi 3.

The biggest change of Raspberry Pi 3 was the integrated WLAN and Bluetooth. But the Bluetooth module uses the serial (UART) interface of the Pi. So after activating the serial interface with ```raspi-config```, there only a Mini-UART available over the GPIO pins. The Mini-UART has a big disatvantage: the baudrate of the Mini-UART depends of the Clock-Speed of the CPU, so a stable serial connection is not possible. You can change that by disabling the Bluetooth module and reconfigure the UART to the GPIO pins. 

Open the "*config.txt*" at the boot directory with admin privilege.

```bash
sudo nano /boot/config.txt
```

Add a new line with ```dtoverlay=pi3-disable-bt``` and if it is not set by ```raspi-config```, add a line with ```enable_uart=1``` [**[3](#references)**]. Now open the file:

```bash
sudo nano /boot/cmdline.txt
```

Delete the part with ```console=serial0,115200``` [**[4](#references)**]. Now you need to stop BT modem trying to use UART:

```bash
sudo systemctl disable hciuart
```

After a reboot, the UART should work like at the previous Raspberry Pi version. The UART is available under "*/dev/ttyAMA0*".


<div id='install-python-packages'/>

##### Install Python-Packages

The test-programs needs the following python-modules:
* ptvsd
* serial (pyserial)
* pigpio

You can check, whether these modules are available with the bash-command:
```bash
pip3 list
```

If one of these modules are missing, you can install it with the bash-command:
```bash
pip3 install <module-name>
```

<div id='activate-pigpio-daemon'/>

##### Activate PiGPIO-Daemon
The test-programs uses PiGPIO to access the GPIO pins. The PiGPIO module needs a daemon-process, which handles the communication between GPIOs and the module [**[5](#references)**]. You can start the daemon-process with:

```bash
sudo pigpiod
```

If you want to start the daemon-process with every bootup of the Raspberry pi, you need to open the ```rc.local```:

```bash
sudo nano /etc/rc.local
```

There you add a line with ```pigpiod``` before ```exit 0```. The file should be look like:

```bash
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

# Print the IP address
_IP=$(hostname -I) || true
if [ "$_IP" ]; then
  printf "My IP address is %s\n" "$_IP"
fi

pigpiod

exit 0
```

<div id='test-program'/>

## <br><p>&#x2049; Test-Program</p>
The test-programs demonstrate the functionality of the Xcom_API-class. To use these programs a Raspberry Pi with a Raspicomm extender module and a RS232-bridge called Xcom-232i is required. Make sure you have setup your Raspberry Pi correctly, just like explained in section [Hardware Setup](#hardware-setup) or you use the available Image-File of the Raspberry Pi, where everything is ready configured.

There are two test-programs available:
* [Xcom-Test-Loop-Program](#xcom-test-loop-program)
* [Xcom-Test-Program](#xcom-test-program)

In the following sections, there will be described these programs and explained how to run these programs.

### Run Test-Program
To run the test-programs make sure, that the Xcom_API.py is inside the python search-path. More Informations about that can you find in section: [Create and Delete an Object](#create-and-delete-an-object). The test-programs needs the following python-modules:
* ptvsd
* serial (pyserial)
* pigpio

You can check, whether these modules are available with the bash-command:
```bash
pip3 list
```

If one of these modules are missing, you can install it with the bash-command:
```bash
pip3 install <module-name>
```

You can start the test-program with the bash-command:

```bash
python3 <program-name>.py
```
The "*\<program-name>*" should be either "*Xcom_Test_Loop_Program*" or "*Xcom_Test_Program*". After starting one of these test-programs, it will start the  program-setup and will ask you for some initialize parameters. These are:
* COM-Port (Normally: /dev/ttyAMA0)
* Baudrate (depends on your Xcom-232i setup)
* Destination-Address (Xtender-Module)
* Soure-Address (Normally your-Raspberry Pi: 1)
* CRC-Check (True/1 or False/0)

You can skip the program-setup by starting the test-program with the mentioned parameters. The sequence of the parameters must not be changed. For example:
```bash
python3 <program-name>.py /dev/ttyAMA0 115200 101 1 True
```

If everything is ok, you are now inside the main menu of the test-program and you can follow the instructions, which are displayed.

### Xcom-Test-Loop-Program
The Xcom-Test-Loop-Program sends cyclical a request to a Xtender-System and display whose answer. After starting the Xcom-Test-Loop-Program and after finishing the program-setup, you need to enter an Object-ID, which is used to encode the request-frame with the method "*get_read_frame*". The Object_IDs are mentioned under section: [Class-Attributes](#class-attributes). Then the test-program sends the request and receive the answer over the serial connection. The answer will be decode with the method "*get_data_from_frame*" and displayed. The loop of the test-program run as fast as possible and is limited by the transfer speed of the serial connection and of the CAN-BUS load.

### Xcom-Test-Program
This program demonstrate the functionality of the Xcom_API-class. After starting the Xcom-Test-Program and after finishing the program-setup, you can either enter an Information-Method to test their functionallity or you enter a function, which demonstrate the functionallity of the Public-Class-Methods. The Xcom-Test-Program is user-friendly designed, so you only need to follow the displayed instructions.

>**Note:** If you want to use the function, which uses the extended Public-Class-Methods, you will need background informations of the byte-frame structure, which are well explained in the technical documentation of the Xcom-232i. Otherwise the Xtender-System or the program will not understand you and will display an error. The link to the documentation of the Xcom-232i can you find under the section: [Hardware Information](#hardware-information).

<div id='references'/>

## <br><p>&#x1F4DA; References </p>
&nbsp;&nbsp;&nbsp; **[1]**&nbsp; Raspberry Pi <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *Installing operating system images on Linux* <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [https://www.raspberrypi.org/documentation/installation/installing-images/linux.md](https://www.raspberrypi.org/documentation/installation/installing-images/linux.md)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(20/08/2017)

&nbsp;&nbsp;&nbsp; **[2]**&nbsp; Raspberry Pi <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *Raspi-Config* <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [https://www.raspberrypi.org/documentation/configuration/raspi-config.md](https://www.raspberrypi.org/documentation/configuration/raspi-config.md) (20/08/2017)

&nbsp;&nbsp;&nbsp; **[3]**&nbsp; Hudson, G. <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *Raspberry Pi 3 compatibility (BT disable & serial port remap fix)* <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [https://openenergymonitor.org/forum-archive/node/12311.html](https://openenergymonitor.org/forum-archive/node/12311.html) (20/08/2017)

&nbsp;&nbsp;&nbsp; **[4]**&nbsp; Raspberry Tips <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *UART auf dem RaspberryPi nutzen* <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [https://raspberry.tips/raspberrypi-einsteiger/uart-auf-dem-raspberrypi-nutzen/](https://raspberry.tips/raspberrypi-einsteiger/uart-auf-dem-raspberrypi-nutzen/) (20/08/2017)

&nbsp;&nbsp;&nbsp; **[5]**&nbsp; PiGPIO <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *PiGPIO Daemon* <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [http://abyz.co.uk/rpi/pigpio/pigpiod.html](http://abyz.co.uk/rpi/pigpio/pigpiod.html) (20/08/2017)

---

**Hochschule Anhalt | Anhalt University of Applied Sciences | Department 6 EMW <br> Xcom-API**

<p>Tobias Müller, M. Eng.<br>
<a href="mailto:Tobias.Mueller@HS-Anhalt.de">&#x1F4E7; Tobias.Mueller@HS-Anhalt.de</a></p>

<p>&#x00A9; es-lab.de, 10.07.2018</p>