From 70c22f3cbc3f535976da2280d2b8d73897b9dee7 Mon Sep 17 00:00:00 2001
From: ChevrierVincent <chevrier6@univ-lorraine.fr>
Date: Tue, 17 Jan 2023 16:30:37 +0100
Subject: [PATCH] maj armoire

---
 .idea/.gitignore                              |    2 +
 .idea/TPBlockChain.iml                        |   12 +
 .../inspectionProfiles/profiles_settings.xml  |    6 +
 .idea/misc.xml                                |    4 +
 .idea/modules.xml                             |    8 +
 .idea/vcs.xml                                 |    6 +
 TP2/.gitkeep                                  |    0
 TP2/Armoire5.py                               |  154 +++
 TP2/Armoire6.py                               |  157 +++
 TP2/__pycache__/Armoire5.cpython-38.pyc       |  Bin 0 -> 5542 bytes
 TP2/__pycache__/Armoire5.cpython-39.pyc       |  Bin 0 -> 5541 bytes
 TP2/__pycache__/Armoire6.cpython-38.pyc       |  Bin 0 -> 5572 bytes
 TP2/__pycache__/Armoire6.cpython-39.pyc       |  Bin 0 -> 5570 bytes
 TP2/__pycache__/bitManip.cpython-38.pyc       |  Bin 0 -> 895 bytes
 TP2/__pycache__/bitManip.cpython-39.pyc       |  Bin 0 -> 895 bytes
 TP2/bitManip.py                               |   38 +
 TP2/docArmoirePython.md                       |   43 +
 TP2/easymodbus/__init__.py                    |    3 +
 .../__pycache__/__init__.cpython-38.pyc       |  Bin 0 -> 164 bytes
 .../__pycache__/modbusClient.cpython-38.pyc   |  Bin 0 -> 24171 bytes
 .../modbusException.cpython-38.pyc            |  Bin 0 -> 3918 bytes
 TP2/easymodbus/easyModbusGUI.py               |  308 +++++
 TP2/easymodbus/modbusClient.py                | 1048 +++++++++++++++++
 TP2/easymodbus/modbusException.py             |  110 ++
 TP2/easymodbus/run.py                         |   33 +
 TP2/test5.py                                  |   90 ++
 TP2/test6.py                                  |   90 ++
 27 files changed, 2112 insertions(+)
 create mode 100644 .idea/.gitignore
 create mode 100644 .idea/TPBlockChain.iml
 create mode 100644 .idea/inspectionProfiles/profiles_settings.xml
 create mode 100644 .idea/misc.xml
 create mode 100644 .idea/modules.xml
 create mode 100644 .idea/vcs.xml
 create mode 100644 TP2/.gitkeep
 create mode 100644 TP2/Armoire5.py
 create mode 100644 TP2/Armoire6.py
 create mode 100644 TP2/__pycache__/Armoire5.cpython-38.pyc
 create mode 100644 TP2/__pycache__/Armoire5.cpython-39.pyc
 create mode 100644 TP2/__pycache__/Armoire6.cpython-38.pyc
 create mode 100644 TP2/__pycache__/Armoire6.cpython-39.pyc
 create mode 100644 TP2/__pycache__/bitManip.cpython-38.pyc
 create mode 100644 TP2/__pycache__/bitManip.cpython-39.pyc
 create mode 100644 TP2/bitManip.py
 create mode 100644 TP2/docArmoirePython.md
 create mode 100644 TP2/easymodbus/__init__.py
 create mode 100644 TP2/easymodbus/__pycache__/__init__.cpython-38.pyc
 create mode 100644 TP2/easymodbus/__pycache__/modbusClient.cpython-38.pyc
 create mode 100644 TP2/easymodbus/__pycache__/modbusException.cpython-38.pyc
 create mode 100644 TP2/easymodbus/easyModbusGUI.py
 create mode 100644 TP2/easymodbus/modbusClient.py
 create mode 100644 TP2/easymodbus/modbusException.py
 create mode 100644 TP2/easymodbus/run.py
 create mode 100644 TP2/test5.py
 create mode 100644 TP2/test6.py

diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..e7e9d11
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,2 @@
+# Default ignored files
+/workspace.xml
diff --git a/.idea/TPBlockChain.iml b/.idea/TPBlockChain.iml
new file mode 100644
index 0000000..8b8c395
--- /dev/null
+++ b/.idea/TPBlockChain.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+  <component name="PyDocumentationSettings">
+    <option name="format" value="PLAIN" />
+    <option name="myDocStringFormat" value="Plain" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..2d83d70
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (2)" project-jdk-type="Python SDK" />
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..6fc7816
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/TPBlockChain.iml" filepath="$PROJECT_DIR$/.idea/TPBlockChain.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/TP2/.gitkeep b/TP2/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/TP2/Armoire5.py b/TP2/Armoire5.py
new file mode 100644
index 0000000..605eba6
--- /dev/null
+++ b/TP2/Armoire5.py
@@ -0,0 +1,154 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Mon Jun 22 16:40:33 2020
+
+@author: chevrier6
+"""
+from bitManip import *
+from easymodbus.modbusClient import ModbusClient
+from easymodbus.modbusClient import convert_registers_to_float
+
+
+class AutomateException(Exception):
+    def __init__(self, message):
+        self.message = message
+
+
+class Armoire5():
+    # ici les adresse des mesure commence  a ZERO (pas UN comme en java)
+
+    def __init__(self):
+        self.nbCharge = 7  # de 0 a 6
+        self.ipAdresse = "100.75.155.115"
+        self.adresseMesure = 2
+        self.adresseTOR = 32000
+        self.adresseMesureSecteur1 = 7  # attention  vraie adresse ()
+        self.adresseMesureSecteur2 = 8  # attention  vraie adresse
+
+        self.debutAdrCharge = 9
+        self.debutAdrSource = 0
+
+    def okCharge(self, i):
+        return 0 <= i <= self.nbCharge - 1 ###########♦ MODIF
+
+    def resetAll(self):
+        self.writeTOR(0)
+
+    def resetSource(self):
+        for i in range(self.nbCharge):
+            self.setSource1(i)
+
+    def resetCharge(self):
+        for i in range(self.nbCharge):
+            self.unsetCharge(i)
+
+    def setCharge(self, charge: int):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = setBit(val, charge + self.debutAdrCharge)
+        self.writeTOR(val)
+
+    def unsetCharge(self, charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = clearBit(val, charge + self.debutAdrCharge)
+        self.writeTOR(val)
+
+    def toggleCharge(self, charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = toggleBit(val, charge + self.debutAdrCharge)
+        self.writeTOR(val)
+
+    def setSource1(self, charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = clearBit(val, charge + self.debutAdrSource)
+        self.writeTOR(val)
+
+    def setSource2(self, charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = setBit(val, charge + self.debutAdrSource)
+        self.writeTOR(val)
+
+    def togglesource(self, charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = toggleBit(val, charge + self.debutAdrSource)
+        self.writeTOR(val)
+
+    ################################
+
+    def writeTOR(self, val):
+        modbusclient = ModbusClient(self.ipAdresse, 502)
+        modbusclient.connect()
+        modbusclient.write_single_register(self.adresseTOR, val)
+        modbusclient.close()
+        # some tempo to wait measure to stabilize
+        from time import sleep
+        sleep(2.)
+
+    def readTOR(self):
+        modbusclient = ModbusClient(self.ipAdresse, 502)
+        modbusclient.connect()
+        inputRegisters = modbusclient.read_inputregisters(self.adresseTOR, 1)
+        modbusclient.close()
+        return (int)(inputRegisters[0])
+
+    ###############################################
+    def readSecteur1(self):
+        addr = self.adresseMesure + (self.adresseMesureSecteur1) * 8
+        return self.lireValeurAdresse(addr + 2), self.lireValeurAdresse(addr), self.lireValeurAdresse(
+            addr + 4), self.lireValeurAdresse(addr + 6)
+
+    def readSecteur2(self):
+        addr = self.adresseMesure + (self.adresseMesureSecteur2) * 8
+        return self.lireValeurAdresse(addr + 2), self.lireValeurAdresse(addr), self.lireValeurAdresse(
+            addr + 4), self.lireValeurAdresse(addr + 6)
+
+    def readMesureCourant(self, source: int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source, 0)
+
+    def readMesureTension(self, source: int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source, 2)
+
+    def readMesurePactive(self, source: int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source, 4)
+
+    def readMesurePreactive(self, source: int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source, 6)
+
+    def readMesure(self, source):
+        return self.readMesureTension(source), self.readMesureCourant(source), self.readMesurePactive(
+            source), self.readMesurePreactive(source)
+
+    def lireValeur(self, source, offset):
+
+        addr = self.adresseMesure + (source) * 8 + offset
+        return self.lireValeurAdresse(addr)
+
+    def lireValeurAdresse(self, addr):
+
+        modbusclient = ModbusClient(self.ipAdresse, 502)
+        modbusclient.connect()
+        data = modbusclient.read_holdingregisters(addr, 2)
+        modbusclient.close()
+        res = convert_registers_to_float(data)
+
+        return res[0]
+
diff --git a/TP2/Armoire6.py b/TP2/Armoire6.py
new file mode 100644
index 0000000..3063525
--- /dev/null
+++ b/TP2/Armoire6.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Mon Jun 22 16:40:33 2020
+
+@author: chevrier6
+"""
+from bitManip import *
+from easymodbus.modbusClient import ModbusClient
+from easymodbus.modbusClient import convert_registers_to_float
+
+class AutomateException(Exception):
+    def __init__(self, message):
+        self.message = message
+
+
+
+
+
+class Armoire6():
+    # ici les adresse des mesure commence  a ZERO (pas UN comme en java)
+
+
+    def __init__(self):
+        self.nbCharge=7 # de 0 a 6
+        self.ipAdresse="100.75.155.116"
+        self.adresseMesure=0
+        self.adresseTOR=32000
+        self.adresseMesureSecteur1=7 # attention  vraie adresse ()
+        self.adresseMesureSecteur2=8 # attention  vraie adresse
+
+        self.debutAdrCharge=0
+        self.debutAdrSource=7
+
+    def okCharge(self,i):
+        return 0 <= i <= self.nbCharge-1
+    
+    def resetAll(self):
+        self.writeTOR(0)
+    
+    def resetSource(self):
+        for i in range(self.nbCharge):
+            self.setSource1(i)
+    
+    def resetCharge(self):
+        for i in range(self.nbCharge):
+            self.unsetCharge(i)
+            
+    def setCharge(self, charge : int ):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val=self.readTOR()
+        val=setBit(val,charge+self.debutAdrCharge)
+        self.writeTOR(val)
+    
+
+    def unsetCharge(self,charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val=self.readTOR()
+        val=clearBit(val,charge+self.debutAdrCharge)
+        self.writeTOR(val)
+
+    def toggleCharge(self, charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = toggleBit(val, charge+self.debutAdrCharge)
+        self.writeTOR(val)
+    
+    def setSource1(self,charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val=self.readTOR()
+        val=clearBit(val,charge+self.debutAdrSource)
+        self.writeTOR(val)
+
+    def setSource2(self, charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val = self.readTOR()
+        val = setBit(val, charge +self.debutAdrSource)
+        self.writeTOR(val)
+
+
+  
+    def togglesource(self,charge):
+        if not self.okCharge(charge):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        val=self.readTOR()
+        val=toggleBit(val,charge+self.debutAdrSource)
+        self.writeTOR(val)
+    
+    ################################
+    
+    
+    def writeTOR(self,val):
+        modbusclient =ModbusClient(self.ipAdresse,502)
+        modbusclient.connect()
+        modbusclient.write_single_register(self.adresseTOR,val)
+        modbusclient.close()
+        # some tempo to wait measure to stabilize
+        from time import sleep
+        sleep(2.)
+    
+    
+    def readTOR(self):
+        modbusclient =ModbusClient(self.ipAdresse,502)
+        modbusclient.connect()
+        inputRegisters = modbusclient.read_inputregisters(self.adresseTOR, 1)
+        modbusclient.close()
+        return (int)(inputRegisters[0])
+        
+###############################################
+    def readSecteur1(self):
+        from time import sleep
+        addr = self.adresseMesure  + (self.adresseMesureSecteur1 ) * 8
+        return self.lireValeurAdresse(addr + 2), self.lireValeurAdresse(addr), self.lireValeurAdresse(addr + 4), self.lireValeurAdresse(addr + 6)
+    def readSecteur2(self):
+        addr = self.adresseMesure  + (self.adresseMesureSecteur2 ) * 8
+        return self.lireValeurAdresse(addr+2),self.lireValeurAdresse(addr),self.lireValeurAdresse(addr+4),self.lireValeurAdresse(addr+6)
+        
+    def readMesureCourant(self,source :int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source,0 )
+    def readMesureTension(self,source :int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source,2 )
+    def readMesurePactive(self,source :int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source,4 )
+    def readMesurePreactive(self,source :int):
+        if not self.okCharge(source):
+            raise AutomateException("numero charge pas compris entre 0 et 6")
+        return self.lireValeur(source,6 )
+
+    def readMesure(self,source):
+        return self.readMesureTension(source),self.readMesureCourant(source),self.readMesurePactive(source),self.readMesurePreactive(source)
+   
+    def lireValeur(self,source,offset):
+
+        addr=  self.adresseMesure  + (source ) *8+offset
+        return self.lireValeurAdresse(addr)
+    def lireValeurAdresse(self,addr):
+
+
+        modbusclient =ModbusClient(self.ipAdresse,502)
+        modbusclient.connect()
+        data=modbusclient.read_holdingregisters(addr,2)
+        modbusclient.close()
+        res =convert_registers_to_float(data)
+       
+        return res[0]
+        
+        
\ No newline at end of file
diff --git a/TP2/__pycache__/Armoire5.cpython-38.pyc b/TP2/__pycache__/Armoire5.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..dc0c29328822cc7d2ab02fa499ac18483c67c216
GIT binary patch
literal 5542
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

literal 0
HcmV?d00001

diff --git a/TP2/__pycache__/Armoire5.cpython-39.pyc b/TP2/__pycache__/Armoire5.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..750a157ccd1c8ff5791bae08ab9b2a2cd5680ab4
GIT binary patch
literal 5541
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

literal 0
HcmV?d00001

diff --git a/TP2/__pycache__/Armoire6.cpython-38.pyc b/TP2/__pycache__/Armoire6.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b54c26efa12a459cc6a298cb10fb4044e8f975d8
GIT binary patch
literal 5572
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

literal 0
HcmV?d00001

diff --git a/TP2/__pycache__/Armoire6.cpython-39.pyc b/TP2/__pycache__/Armoire6.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..f9cc62dd27f5c43adea4b6064ad935f7c989130b
GIT binary patch
literal 5570
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

literal 0
HcmV?d00001

diff --git a/TP2/__pycache__/bitManip.cpython-38.pyc b/TP2/__pycache__/bitManip.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..57fc49c64a676aabb5e2291b23cca6cb93d92c66
GIT binary patch
literal 895
zcmWIL<>g{vU|?wHyq`FOnStRkh=Yuo7#J8F7#J9e4Hy_0QW&BbQW#U1S{R}jQ<zg&
zS{S03Qdm>iS{S03Q`l2DS{R~OQaDq%S{R~OQ@Dc}G<m8lxtxnq6H8K46!P;FeDm`Z
zyh`&FjEocv&8$p}txPQxj0}tnxVRh=OG`5Hi>wrqGg8ZnGE<ApxRM!>+`-JizyQL|
zAg9QIoWfYkSi(@l(9Gz<5X)1`RKu9UWXVv=Sjbbu7|fu_TqRtbn47AQSgcT-TH=&h
zqEV(}p!pJH<V%p3G#PKP7A5ATr)o0aVl2DGm~@LVb0tF&I|Bp5FFR+en9$<XqT(31
zV`5xVi?d7e3t~zNbdwB?bc<7p%ae3-6N^hyi(*0ojAD{9OMDaaG7IzyDsQpnCKhKK
znsI`h$^r5N6AL2`BNt;4NF*6#J4g_OK|TWU!M+jz`>KY~j-i&RhM|VZfgzY-C6iwf
z$jxAftz?ek$jmE=FR3g@y~UQFmR6iva*G9I8CV)ZfGoVlUXof2^0W}h2`nI+7&#b=
z_!t-%h_~K}A(){Elr|vdax*Y6Kv<wKDgs->1_@dT6kGW5+5&P>3M0sq{7Bv;U=K%f
zPHJM2Q)US$;)@~v;bJTT1sL)EaU|>?&XWA}^qf?u%n}t8F9|X*F!*V*-C~cAPsvY?
uj|WF2I5>+yz6Cp^2&4!pfDoa?VUwGmQks)$2a4%pP>8ayb8vF7fgk{gxSk;Z

literal 0
HcmV?d00001

diff --git a/TP2/__pycache__/bitManip.cpython-39.pyc b/TP2/__pycache__/bitManip.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2da8f09a8e9dbcb2193a38cc1d2dfc191a8a9410
GIT binary patch
literal 895
zcmYe~<>g{vU|?wHyq`FOnStRkh=Yuo7#J8F7#J9e4Hy_0QW&BbQW#U1S{R}jQ<zg&
zS{S03Qdm>iS{S03Q`l2DS{R~OQaDq%S{R~OQ@Dc}G<m8lxtxnq6H8K46!P;FeDm`Z
zyh`&FjEocv&8$p}txPQxj0}tnxVRh=OG`5Hi>wrqGg8ZnGE<ApxRM!>+`-JizyQL|
zAg9QIoWfYkSi(@l(9Gz<5X)1`RKu9UWXVv=Sjbbu7|fu_TqRtbn47AQSgcT-TH=&h
zqEV(}p!pJH<V%p3G#PKP7A5ATr)o0aVl2DGm~@LVb0tF&I|Bp5FFR+en9$<XqT(31
zV`5xVi?d7e3t~zNbdwB?bc<7p%ae3-6N^hyi(*0ojAD{9OMDaaG7IzyDsQpnCKhKK
znsI`h$^r5N6AL2`BNt;4NF*6#J4g_OK|TWU!M+jz`>KY~j-i&RhM|VZfgzY-C6iwf
z$jxAftz?ek$jmE=FR3g@y~UQFmR6iva*G9I8CV)ZfGoVlUXof2^0W}h2`nI+7&#b=
z_!t-%h_~K}A(){Elr|vdax*Y6Kv<wKDgs->1_@dT6kGW5+5&P>3M0sq{7Bv;U=K%f
zPHJM2Q)US$;)@~v;bJTT1sL)EaU|>?&XWA}^qf?u%n}t8F9|X*F!*V*-C~cAPsvY?
uj|WF2I5>+yz6Cp^2&4!pfDoa?VUwGmQks)$2a4%pP>8ayb8vF7fgk{~te!0Z

literal 0
HcmV?d00001

diff --git a/TP2/bitManip.py b/TP2/bitManip.py
new file mode 100644
index 0000000..2f8ceb2
--- /dev/null
+++ b/TP2/bitManip.py
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Mon Jun 22 16:43:58 2020
+
+@author: chevrier6
+"""
+
+######################
+def mask16(v):
+    "same as setBit(v,0)"
+    b=1
+    for i in range(v):
+        b*=2
+    return b
+
+# 4 next functions from https://wiki.python.org/moin/BitManipulation
+# testBit() returns a nonzero result, 2**offset, if the bit at 'offset' is one.
+def testBit(int_type, offset):
+    mask = 1 << offset
+    return(int_type & mask)
+
+  # setBit() returns an integer with the bit at 'offset' set to 1.
+
+def setBit(int_type, offset):
+    mask = 1 << offset
+    return(int_type | mask)
+
+ # clearBit() returns an integer with the bit at 'offset' cleared.
+
+def clearBit(int_type, offset):
+    mask = ~(1 << offset)
+    return(int_type & mask)
+
+ # toggleBit() returns an integer with the bit at 'offset' inverted, 0 -> 1 and 1 -> 0.
+
+def toggleBit(int_type, offset):
+    mask = 1 << offset
+    return(int_type ^ mask)
\ No newline at end of file
diff --git a/TP2/docArmoirePython.md b/TP2/docArmoirePython.md
new file mode 100644
index 0000000..95dcaa3
--- /dev/null
+++ b/TP2/docArmoirePython.md
@@ -0,0 +1,43 @@
+# Une armoire c'est quoi ?
+
+- c'est un appareil électrique commandable à distance
+- il dispose de 7 charges différentes (numérotées de 0 à 6)  et de deux source d'alimentation 
+(source1 et source2)
+
+- chaque charge peut être en marche ou pas et soit sur source 1 soit sur source 2 indépendament des autres
+- on peut connaitre des infos sur chaque charges (U,I,P,PR) et sur chaque source (i.e. le cumul des charges en marche sur la source concernée)
+# Documentation code python de manipulation des armoires
+
+
+## Prerequis logiciel
+
+- utilisation de la librairie EasyModbus.py
+- utilisation d'un code bitManip.py
+
+## Code disponible
+
+### Note
+Actuellemnt seul le code pour l'armoire 6 est opérationnel
+
+### Utilisation
+
+- charger le fichier correspondant à l'armoire à utiliser (exemple Armoire6.py) et ses dépendances
+
+**Méthodes**
+
+* Constructeur *ArmoireX()* où X vaut 6
+
+* actions générales
+    - **resetAll**: remet tout à l'état d'origine
+    - **resetSource** / **resetCharge**: remet la partie source/charge à l'état d'origine
+ * actions sur les charges  
+    - **setCharge** / **unsetCharge** / **toggleCharge**(*n°charge*): met sur ON/OFF/état inverse la charge. *N°charge* doit être compris entre 0 et 6
+* Actions sur les sources
+    - **setSource1** / **setSource2** / **togglesource**(*n°charge*): met sur l'alimentaion 1/l'alimentation 2/inverse la source. *N°charge* doit être compris entre 0 et 6
+* Actions sur les sources
+   
+* lecture de valeurs (
+retourne une liste de valeurs  [U,I,PA,PR])
+    - **readSecteur1**: mesure pour la source 1
+    - **readSecteur2**: mesure pour la source 2
+    - **readMesure**(*n°charge*): mesure pour la charge paramètre (compris en 0 et 6)
\ No newline at end of file
diff --git a/TP2/easymodbus/__init__.py b/TP2/easymodbus/__init__.py
new file mode 100644
index 0000000..5f434bb
--- /dev/null
+++ b/TP2/easymodbus/__init__.py
@@ -0,0 +1,3 @@
+#Only required for Python 2:
+#We Make an empty file called __init__.py in the same directory as the files.
+#That will signify to Python that it's "ok to import from this directory".
diff --git a/TP2/easymodbus/__pycache__/__init__.cpython-38.pyc b/TP2/easymodbus/__pycache__/__init__.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..793146fc0b6713b49233b6cc0dc4fc92f3c85bd2
GIT binary patch
literal 164
zcmWIL<>g{vU|?WUd>gxsfq~&Mh=Yt785kHG7#J9eSr`}?QW%06G#UL?G8BP?5yUS~
zXRDad;?$zznB<JqvZBn?BC{Bm)Z*-t{DPR00^KA-Bi-VZ;_@Wj+{EIN)S{S>0Hc`H
p#Nx`_{FJ29;+XjO%)HE!_;|g7%3B;Zx%nxjIjMFaD?Wpq0sx59DK!89

literal 0
HcmV?d00001

diff --git a/TP2/easymodbus/__pycache__/modbusClient.cpython-38.pyc b/TP2/easymodbus/__pycache__/modbusClient.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c2e7f7cbf118af50ede25a74b3a23406cf228087
GIT binary patch
literal 24171
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
C1@Ddk

literal 0
HcmV?d00001

diff --git a/TP2/easymodbus/__pycache__/modbusException.cpython-38.pyc b/TP2/easymodbus/__pycache__/modbusException.cpython-38.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0dee22613bc74e0574fbf40c102b00e23c6f30c1
GIT binary patch
literal 3918
zcmWIL<>g{vU|^VQ_coTDhk@ZSh=Yt-7#J8F7#J9eD;O9UQW&Bb+!<0BQ<z#9QkYU1
zo0+4S+!<1sQ&?IUQdm-%nwg`R-5F9?Q`lM<QrN(J7I%ge_7sj5h7=AkpVgfqg)@b#
zg&~Ct%x80FNa0T5X<<m=0rT128B%yt_*xiJ_`rOQ6#ifaO@S&yF6W}u#FEq$h5S4P
zLlZp%OFbh4Lo+Tehs4s7jQk=ih2WCZw8T7xp#0+E+{C;*u4H6yfY?khuShU3Fr+d>
zF{Us?F{Lm@F{d!4Ft;#7v81pBGib8j;`hx@Nh&RNtw>HSD9Oyv`z6e!prD|ToRe5w
zoRXhh4B;_@jD%tk8)UjOD4+xw7#M08YZ&4gYM5#m;u%vIgBdiLsy-{g4OA$}S4c`#
zD9I?wFV9oROjCeZs1Tf5RF+z#P?TCyT9j9;kXlrfU!;(npOUJe<W`!O404NtGl-j)
zU!ss&k(yiz3J(o~3Ih{OC9tbN?sP0EDauSLElDl5f{TH~Q!5IJQj3c-^YavRbrmx6
z3Q9qSz{N826v{I)lQR@bGE$*d=O-tZ78RwYpcs>zT3no%o(eJ}wW1&=F)tD9uKYBF
zM!0&vl}xv|5cb|;hiYEQe2b+xH7BhIl)8#o85kH=G8AzzFfjZIaJGsGElw>ej!Di)
zEi1}QEi#L7NiEJU$uEd0DbP(aG}0|jDK1aa%}p#WNiB*A2{4LDO)Rd=%?CwU41|IQ
zv|d5wEsps3%)HE!_;_AW<bW(>U}Iyfl7NIcLMcp{-%3`Hp1j1|)cE*YT=DU_`6;D2
zAU02Yd|_!~4pfFcK0YNsIX=D!lz+gEM<O^G7#NBe85kHqo+<`e%E8FO0u~`VS;_>b
z7G);p1mqW$_~n=Q7o_H;rof$F1WJC%pmYdLk_;d=NDyC|Jb@=o7K3e5D9A4=QOGP-
z042G6u$}PO9ZU(W2;|)&Hc+sGf*cYR;8*}fj|@uGtKthtJ$O1O;zl(MY%bVHP!1P|
z83~S9kO<ikE9{(~mzN68-W0~?MLh9|umn{6KvKU#N@`hVa;idFVrC9fHXk|>s|||<
zaGsVy_z@nE#Kfl{0|SE^%p`Dpf<(xUPeoW^4Jxbs@=JnC3qZMu;@tWcPwYbDlb9L=
zT%mxnb1}?agR}0ypQWu}@db`~ErLN#Oga!^U|=wXnF~$_AQ7_Dfka?wVqQsRNu_6A
zSz=BmrG@n)ilV;|>K27eh+~FgoO{CJ1{~*#xPq6Ms1{~mU~qvM2aalx2-#6BA6$}H
zRFavO?wFDSYGhF-#(z*0<Hb-XDI}&q9Ho$$m!dEn(m@0);=t)ZgFx65lN>}C7#M<K
zrh=0LNQCU<AnqLG?3|IBob3j#SmBisd9Aelc#?s0kh22VrlDJhr^CV>9GeO_f{vJ2
z6lGvwNP?LLjzy4&pC)G!KLZ29Elxx{fSTq-phjB}sHQIh74t=)0-y*K?L{D6kQOAk
e%?Bnx4Zm9)HjvJM9Y}vM9|Hpe3%dY60s;W&D7Qoa

literal 0
HcmV?d00001

diff --git a/TP2/easymodbus/easyModbusGUI.py b/TP2/easymodbus/easyModbusGUI.py
new file mode 100644
index 0000000..fedeb5e
--- /dev/null
+++ b/TP2/easymodbus/easyModbusGUI.py
@@ -0,0 +1,308 @@
+#!/usr/bin/env python
+
+import sys
+
+if sys.version_info[0] < 3:                 #The Module "Tkinter" is named "tkinter" in Python 3.
+    from Tkinter import *
+    import tkMessageBox as messagebox       #We import tkMessageBos as messagebox, because thats the name in Python 3
+
+else:
+    from tkinter import *
+    from builtins import int
+    from future.moves import tkinter
+    import tkinter.messagebox as messagebox
+from easymodbus.modbusClient import *
+
+class EasyModbusGUI(Frame):
+    def __init__(self, master=None):
+        Frame.__init__(self)
+        master.title("EasyModbusPython Client")
+        self.pack()
+        self.createWidgets()
+        
+        
+    def createWidgets(self):
+        self.pack(fill=BOTH, expand=True)
+                
+        self.columnconfigure(1, weight=1)
+        self.columnconfigure(3, pad=7)
+        self.rowconfigure(3, weight=1)
+        self.rowconfigure(5, pad=7)
+        
+        #label Read operations
+        readOperationsLabel = Label(self, text="Read Operations", font = 15)
+        readOperationsLabel.config(font=15)
+        readOperationsLabel.grid(row = 0, column = 0)
+        
+        #Button Read Coils
+        self.readCoils = Button(self, text="Read Coils (FC1)", width=25, command=self.__ReadCoils)
+        self.readCoils.grid(row = 4, column = 0, padx = 20, pady = 6, columnspan=2)
+        
+        #Button Read Discrete Inputs
+        self.readDiscreteInputs = Button(self, text="Read Discrete Inputs (FC2)", width=25, command=self.__ReadDiscreteInputs)
+        self.readDiscreteInputs.grid(row = 5, column = 0, padx = 20, pady = 6, columnspan=2)
+        
+        #Button Read Holding Registers
+        self.readHoldingRegisters = Button(self, text="Read Holding Registers (FC3)", width=25, command=self.__ReadHoldingRegisters)
+        self.readHoldingRegisters.grid(row = 6, column = 0, padx = 20, pady = 6, columnspan=2)
+ 
+        #Button Read Input Registers
+        self.readInputRegisters = Button(self, text="Read Input Registers (FC4)", width=25, command=self.__ReadInputRegisters)
+        self.readInputRegisters.grid(row = 7, column = 0, padx = 20, pady = 6, columnspan=2)       
+        
+        #label for IP Addresses
+        label = Label(self, text="IP-Address:")
+        label.grid(row = 2, column = 0, sticky=W)
+        
+        #Entry for IPAddress
+        self.ipAddressEntry = Entry(self, width=15)
+        self.ipAddressEntry.insert(END, "127.0.0.1")
+        self.ipAddressEntry.grid(row = 3, column = 0, sticky=W)
+        
+        #label for Display Port
+        labelPort = Label(self, text="Port:")
+        labelPort.grid(row = 2, column = 1, sticky=W)
+        
+        #Text Field for Port
+        self.portEntry = Entry(self, width=10)
+        self.portEntry.insert(END, "502")
+        self.portEntry.grid(row = 3, column = 1, sticky=W)
+
+        #label for Display Starting Address
+        labelStartingAddress = Label(self, text="Starting Address:")
+        labelStartingAddress.grid(row = 4, column = 3, sticky=W)
+        
+        #Text Field for starting Address
+        self.startingAddress = Entry(self, width=10)
+        self.startingAddress.insert(END, "1")
+        self.startingAddress.grid(row = 4, column = 4, sticky=W)
+
+        #label for Display Number of values
+        labelStartingAddress = Label(self, text="Number of values:")
+        labelStartingAddress.grid(row = 5, column = 3, sticky=W)
+        
+        #Text Field for number of Values
+        self.quantity = Entry(self, width=10)
+        self.quantity.insert(END, "1")
+        self.quantity.grid(row = 5, column = 4, sticky=W)
+
+        #label for Response from server
+        labelResponse = Label(self, text="Response from Server")
+        labelResponse.grid(row = 2, column = 5, sticky=W, padx = 10)        
+    
+        #Text Field for response from server
+        self.response = StringVar
+        self.responseTextField = Text(self,  width=35, height = 10)
+        scroll = Scrollbar(self, command=self.responseTextField.yview)
+        self.responseTextField.configure(yscrollcommand=scroll.set)
+        self.responseTextField.insert(END, "")
+        self.responseTextField.grid(row = 2, column = 5, rowspan=8, padx = 10) 
+        scroll.grid(row = 3, column = 6, rowspan=5, sticky=N+S+E)
+        
+        #Empty row between Read and Write operations
+        self.rowconfigure(15, minsize=20)
+        
+        #label Write operations
+        readOperationsLabel = Label(self, text="Write Operations", font = 15)
+        readOperationsLabel.config(font=15)
+        readOperationsLabel.grid(row = 20, column = 0)
+        
+        #Label select datatye to write
+        datatype = Label(self, text="Select datatype to write")
+        datatype.grid(row = 25, column = 0,  sticky=W)       
+
+        #Combobox to selct the type of variable to write 
+        lst1 = ['Coils (bool)','Holding Registers (word)']
+        self.variableDatatype = StringVar(self)
+        self.variableDatatype.set('Coils (bool)')
+        self.variableDatatype.trace('w',self.datatypeChanged)
+        dropdown = OptionMenu(self,self.variableDatatype,*lst1)
+        dropdown.grid(row = 25, column = 1,columnspan = 3,  sticky=W)
+
+        #Label select value to write
+        datatype = Label(self, text="Select value to write")
+        datatype.grid(row = 26, column = 0, sticky=W)   #
+        
+        #Combobox to selct true or false in case "coils" has been selcted
+        lst1 = ['FALSE', 'TRUE']
+        self.variableData = StringVar(self)
+        self.variableData.set('FALSE')
+        self.dropdownData = OptionMenu(self,self.variableData,*lst1)
+        self.dropdownData.grid(row = 26, column = 1, sticky=W)
+        
+        #TextField for the Register Values to write
+        self.registerValueToWrite = Entry(self, width=10)
+        self.registerValueToWrite.insert(END, "1")
+        
+        #label for Display startingAddress
+        labelStartingAddress = Label(self, text="Starting Address:")
+        labelStartingAddress.grid(row = 27, column = 0, sticky=W)
+        
+        #Text Field for starting Address
+        self.startingAddressWrite = Entry(self, width=10)
+        self.startingAddressWrite.insert(END, "1")
+        self.startingAddressWrite.grid(row = 27, column = 1, sticky=W)
+        
+        #label for Request to Server
+        labelResponse = Label(self, text="Request to Server")
+        labelResponse.grid(row = 24, column = 5, sticky=W, padx = 10)     
+        
+        #Text Field containing data to write to server
+        self.request = StringVar
+        self.requestTextField = Text(self,  width=35, height = 10)
+        scroll = Scrollbar(self, command=self.requestTextField.yview)
+        self.requestTextField.configure(yscrollcommand=scroll.set)
+        self.requestTextField.insert(END, "")
+        self.requestTextField.grid(row = 25, column = 5, rowspan=8, padx = 10) 
+        scroll.grid(row = 25, column = 6, rowspan=8, sticky=N+S+E)
+        
+        #Button Add Entry to request list
+        self.addEntryToRequestList = Button(self, text="Add Value to \n request list", width=15, command=self.addValueToRequestList)
+        self.addEntryToRequestList.grid(row = 26, column = 3,columnspan = 2)
+        
+        #Button Delete Entry from request list
+        self.addEntryToRequestList = Button(self, text="Delete Value from \n request list", width=15, command=self.deleteValueToRequestList)
+        self.addEntryToRequestList.grid(row = 28, column = 3,columnspan = 2)
+                
+        
+        #Button Write values to server
+        writeValuesToServerButton = Button(self, text="Write Requested Values to Server", width=25, command=self.__writeValuesToServer)
+        writeValuesToServerButton.grid(row = 30, column = 0, padx = 20, pady = 6, columnspan=2)
+        
+    def addValueToRequestList(self):
+        if (self.variableDatatype.get()  == 'Coils (bool)'):
+            self.requestTextField.insert(END, self.variableData.get())  
+            self.requestTextField.insert(END, "\n")
+        else:
+            self.requestTextField.insert(END, self.registerValueToWrite.get())  
+            self.requestTextField.insert(END, "\n")          
+        
+        
+    def datatypeChanged(self,a,b,c):
+        self.requestTextField.delete('1.0', END)
+        if (self.variableDatatype.get()  == 'Coils (bool)'):
+            self.registerValueToWrite.grid_remove()
+            self.dropdownData.grid(row = 26, column = 1, sticky=W)
+        else:
+            self.registerValueToWrite.grid(row = 26, column = 1, sticky=W)
+            self.dropdownData.grid_remove()
+           
+    def onReverse(self):
+        self.name.set(self.name.get()[::-1])
+      
+    def __ReadCoils(self):
+        try:
+            modbusClient = ModbusClient(self.ipAddressEntry.get(), int(self.portEntry.get()))
+            if (not modbusClient.is_connected()):
+                modbusClient.connect()
+            coils = modbusClient.read_coils(int(self.startingAddress.get()) - 1, int(self.quantity.get()))
+            self.responseTextField.delete('1.0', END)
+            for coil in coils:
+                if (coil == FALSE):
+                    response = "FALSE"
+                else:
+                    response = "TRUE"
+                
+                self.responseTextField.insert(END, response  + "\n")
+        except Exception as e:
+            messagebox.showerror('Exception Reading coils from Server', str(e))
+        finally:
+            modbusClient.close()
+        
+    def __ReadDiscreteInputs(self):
+        try:
+            modbusClient = ModbusClient(self.ipAddressEntry.get(), int(self.portEntry.get()))
+            if (not modbusClient.is_connected()):
+                modbusClient.connect()
+            discrInputs = modbusClient.read_discreteinputs(int(self.startingAddress.get()) - 1, int(self.quantity.get()))
+            self.responseTextField.delete('1.0', END)
+            for inp in discrInputs:
+                if (inp == FALSE):
+                    response = "FALSE"
+                else:
+                    response = "TRUE"
+                
+                self.responseTextField.insert(END, response  + "\n")
+        except Exception as e:
+            messagebox.showerror('Exception Reading discrete inputs from Server', str(e))
+        finally:
+            modbusClient.close() 
+   
+    def __ReadHoldingRegisters(self):
+        try:
+            modbusClient = ModbusClient(self.ipAddressEntry.get(), int(self.portEntry.get()))
+            if (not modbusClient.is_connected()):
+                modbusClient.connect()
+            holdingRegisters = modbusClient.read_holdingregisters(int(self.startingAddress.get()) - 1, int(self.quantity.get()))
+            self.responseTextField.delete('1.0', END)
+            for register in holdingRegisters:
+     
+                
+                self.responseTextField.insert(END, str(register)  + "\n")
+        except Exception as e:
+            messagebox.showerror('Exception Reading holding registers from Server', str(e))
+        
+        finally:
+            modbusClient.close()   
+        
+    def __ReadInputRegisters(self):
+        try:
+            modbusClient = ModbusClient(self.ipAddressEntry.get(), int(self.portEntry.get()))
+            if (not modbusClient.is_connected()):
+                modbusClient.connect()
+            inputRegisters = modbusClient.read_inputregisters(int(self.startingAddress.get()) - 1, int(self.quantity.get()))
+            self.responseTextField.delete('1.0', END)
+            for register in inputRegisters:
+                
+                self.responseTextField.insert(END, str(register)  + "\n")
+            
+            modbusClient.close()   
+        except Exception as e:
+            messagebox.showerror('Exception Reading input Registers from Server', str(e))
+      
+    def __writeValuesToServer(self):
+        try:
+            modbusClient = ModbusClient(self.ipAddressEntry.get(), int(self.portEntry.get()))
+            if (not modbusClient.is_connected()):
+                modbusClient.connect()
+            numberOfLines = (int(self.requestTextField.index('end').split('.')[0]) - 2)
+            if (self.variableDatatype.get()  == 'Coils (bool)'):
+                if (numberOfLines > 1):
+                    valueToWrite = list()
+                    for i in range(1, numberOfLines+1):
+                        textFieltValues = str(self.requestTextField.get(str(i)+".0", str(i+1)+".0")[:-1])
+                        if "TRUE" in textFieltValues:           #String comparison contains some ""Null" symbol
+                            valueToWrite.append(1)
+                        else:
+                            valueToWrite.append(0)
+                    modbusClient.write_multiple_coils(int(self.startingAddressWrite.get()) - 1, valueToWrite)
+                else:              
+                    textFieltValues = str(self.requestTextField.get('1.0', END)[:-1])
+                    if "TRUE" in textFieltValues:               #String comparison contains some ""Null" symbol
+                        dataToSend = 1
+                    else:
+                        dataToSend = 0
+                    modbusClient.write_single_coil(int(self.startingAddressWrite.get()) - 1, dataToSend)
+            else:
+                if (numberOfLines > 1):
+                    valueToWrite = list()
+                    for i in range(1, numberOfLines+1):
+                        textFieltValues = int(self.requestTextField.get(str(i)+".0", str(i+1)+".0")[:-1])
+                        valueToWrite.append(textFieltValues)
+                    modbusClient.write_multiple_registers(int(self.startingAddressWrite.get()) - 1, valueToWrite)
+                else:              
+                    textFieltValues = int(self.requestTextField.get('1.0', END)[:-1])
+                    modbusClient.write_single_register(int(self.startingAddressWrite.get()) - 1, textFieltValues)
+        except Exception as e:
+            messagebox.showerror('Exception writing values to Server', str(e))
+        modbusClient.close()
+        
+    def deleteValueToRequestList(self):
+        numberOfLines = (int(self.requestTextField.index('end').split('.')[0]) - 2)
+        cursorPos = int(self.requestTextField.index(INSERT)[0])                     #Find the current Cursorposition e.g. 1.0 -> First line
+        if (cursorPos-1 != numberOfLines):            #don't delete the last line, because the last line contains only a "newline"
+            self.requestTextField.delete(str(cursorPos)+".0",str(cursorPos+1)+".0")     #Delete the whole line using e.g. delete("1.0","2.0) deletes the first line
+      
+root = Tk()
+app = EasyModbusGUI(root)
+app.mainloop()
\ No newline at end of file
diff --git a/TP2/easymodbus/modbusClient.py b/TP2/easymodbus/modbusClient.py
new file mode 100644
index 0000000..8801033
--- /dev/null
+++ b/TP2/easymodbus/modbusClient.py
@@ -0,0 +1,1048 @@
+'''
+Created on 12.09.2016
+
+@author: Stefan Rossmann
+'''
+import importlib
+import easymodbus.modbusException as Exceptions
+import socket
+import struct
+import threading
+
+
+class ModbusClient(object):
+    """
+    Implementation of a Modbus TCP Client and a Modbus RTU Master
+    """
+
+    def __init__(self, *params):
+        """
+        Constructor for Modbus RTU (serial line):
+        modbusClient = ModbusClient.ModbusClient('COM1')
+        First Parameter is the serial Port 
+        
+        Constructor for Modbus TCP:
+        modbusClient = ModbusClient.ModbusClient('127.0.0.1', 502)
+        First Parameter ist the IP-Address of the Server to connect to
+        Second Parameter is the Port the Server listens to
+        """
+        self.__receivedata = bytearray()
+        self.__transactionIdentifier = 0
+        self.__unitIdentifier = 1
+        self.__timeout = 5
+        self.__ser = None
+        self.__tcpClientSocket = None
+        self.__connected = False
+        # Constructor for RTU
+        if len(params) == 1 & isinstance(params[0], str):
+            serial = importlib.import_module("serial")
+            self.serialPort = params[0]
+            self.__baudrate = 9600
+            self.__parity = Parity.even
+            self.__stopbits = Stopbits.one
+            self.__transactionIdentifier = 0
+            self.__ser = serial.Serial()
+
+        # Constructor for TCP
+        elif (len(params) == 2) & isinstance(params[0], str) & isinstance(params[1], int):
+            self.__tcpClientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            self.__ipAddress = params[0]
+            self.__port = params[1]
+
+    def connect(self):
+        """
+        Connects to a Modbus-TCP Server or a Modbus-RTU Slave with the given Parameters
+        """
+        if self.__ser is not None:
+            serial = importlib.import_module("serial")
+            if self.__stopbits == 0:
+                self.__ser.stopbits = serial.STOPBITS_ONE
+            elif self.__stopbits == 1:
+                self.__ser.stopbits = serial.STOPBITS_TWO
+            elif self.__stopbits == 2:
+                self.__ser.stopbits = serial.STOPBITS_ONE_POINT_FIVE
+            if self.__parity == 0:
+                self.__ser.parity = serial.PARITY_EVEN
+            elif self.__parity == 1:
+                self.__ser.parity = serial.PARITY_ODD
+            elif self.__parity == 2:
+                self.__ser.parity = serial.PARITY_NONE
+
+            self.__ser = serial.Serial(self.serialPort, self.__baudrate, timeout=self.__timeout,
+                                       parity=self.__ser.parity, stopbits=self.__ser.stopbits, xonxoff=0, rtscts=0)
+            self.__ser.writeTimeout = self.__timeout
+        # print (self.ser)
+        if self.__tcpClientSocket is not None:
+            self.__tcpClientSocket.settimeout(5)
+            self.__tcpClientSocket.connect((self.__ipAddress, self.__port))
+
+            self.__connected = True
+            self.__thread = threading.Thread(target=self.__listen, args=())
+            self.__thread.start()
+
+    def __listen(self):
+        self.__stoplistening = False
+        self.__receivedata = bytearray()
+        try:
+            while not self.__stoplistening:
+                if len(self.__receivedata) == 0:
+                    self.__receivedata = bytearray()
+                    self.__timeout = 500
+                    if self.__tcpClientSocket is not None:
+                        self.__receivedata = self.__tcpClientSocket.recv(256)
+        except socket.timeout:
+            self.__receivedata = None
+
+    def close(self):
+        """
+        Closes Serial port, or TCP-Socket connection
+        """
+        if self.__ser is not None:
+            self.__ser.close()
+        if self.__tcpClientSocket is not None:
+            self.__stoplistening = True
+            self.__tcpClientSocket.shutdown(socket.SHUT_RDWR)
+            self.__tcpClientSocket.close()
+        self.__connected = False
+
+    def read_discreteinputs(self, starting_address, quantity):
+        """
+        Read Discrete Inputs from Master device (Function code 2)
+        starting_address: First discrete input to be read
+        quantity: Numer of discrete Inputs to be read
+        returns: Boolean Array [0..quantity-1] which contains the discrete Inputs
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        if (starting_address > 65535) | (quantity > 2000):
+            raise ValueError("Starting address must be 0 - 65535; quantity must be 0 - 2000")
+        function_code = 2
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        quantity_lsb = quantity & 0xFF
+        quantity_msb = (quantity & 0xFF00) >> 8
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, quantity_msb,
+                 quantity_lsb, 0, 0])
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data[6] = crcLSB
+            data[7] = crcMSB
+            self.__ser.write(data)
+            if quantity % 8 != 0:
+                bytes_to_read = 6 + int(quantity / 8)
+            else:
+                bytes_to_read = 5 + int(quantity / 8)
+            data = self.__ser.read(bytes_to_read)
+            b = bytearray(data)
+            data = b
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError('Read timeout Exception')
+            if (data[1] == 0x82) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x82) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x82) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x82) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+            myList = list()
+            for i in range(0, quantity):
+                myList.append(bool((data[int(i / 8) + 3] >> int(i % 8)) & 0x1))
+            return myList
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, quantity_msb, quantity_lsb])
+            self.__tcpClientSocket.send(data)
+            self.__receivedata = bytearray()
+            if quantity % 8 != 0:
+                bytes_to_read = 9 + int(quantity / 8)
+            else:
+                bytes_to_read = 8 + int(quantity / 8)
+            try:
+                while len(self.__receivedata) == 0:
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+
+            data = bytearray(self.__receivedata)
+
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            myList = list()
+            for i in range(0, quantity):
+                myList.append(bool((data[int(i / 8) + 3 + 6] >> int(i % 8)) & 0x1))
+            return myList
+
+    def read_coils(self, starting_address, quantity):
+        """
+        Read Coils from Master device (Function code 1)
+        starting_address:  First coil to be read
+        quantity: Numer of coils to be read
+        returns:  Boolean Array [0..quantity-1] which contains the coils
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        if (starting_address > 65535) | (quantity > 2000):
+            raise ValueError("Starting address must be 0 - 65535; quantity must be 0 - 2000")
+        function_code = 1
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        quantity_lsb = quantity & 0xFF
+        quantity_msb = (quantity & 0xFF00) >> 8
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, quantity_msb,
+                 quantity_lsb, 0, 0])
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data[6] = crcLSB
+            data[7] = crcMSB
+            self.__ser.write(data)
+            if quantity % 8 != 0:
+                bytes_to_read = 6 + int(quantity / 8)
+            else:
+                bytes_to_read = 5 + int(quantity / 8)
+            data = self.__ser.read(bytes_to_read)
+            b = bytearray(data)
+            data = b
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError('Read timeout Exception')
+            if (data[1] == 0x81) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x81) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x81) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x81) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+            myList = list()
+            for i in range(0, quantity):
+                myList.append(bool((data[int(i / 8) + 3] >> int(i % 8)) & 0x1))
+            return myList
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, quantity_msb, quantity_lsb])
+            self.__tcpClientSocket.send(data)
+            self.__receivedata = bytearray()
+            if (quantity % 8 != 0):
+                bytes_to_read = 10 + int(quantity / 8)
+            else:
+                bytes_to_read = 9 + int(quantity / 8)
+            try:
+                while len(self.__receivedata) == 0:
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+            data = bytearray(self.__receivedata)
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1 + 6] == 0x82) & (data[2 + 6] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            myList = list()
+            for i in range(0, quantity):
+                myList.append(bool((data[int(i / 8) + 3 + 6] >> int(i % 8)) & 0x1))
+            return myList
+
+    def read_holdingregisters(self, starting_address, quantity):
+        """
+        Read Holding Registers from Master device (Function code 3)
+        starting_address: First holding register to be read
+        quantity:  Number of holding registers to be read
+        returns:  Int Array [0..quantity-1] which contains the holding registers
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        if (starting_address > 65535) | (quantity > 125):
+            raise ValueError("Starting address must be 0 - 65535; quantity must be 0 - 125")
+        function_code = 3
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        quantity_lsb = quantity & 0xFF
+        quantity_msb = (quantity & 0xFF00) >> 8
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, quantity_msb,
+                 quantity_lsb, 0, 0])
+
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data[6] = crcLSB
+            data[7] = crcMSB
+
+            self.__ser.write(data)
+            bytes_to_read = 5 + int(quantity * 2)
+            data = self.__ser.read(bytes_to_read)
+            b = bytearray(data)
+            data = b
+
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError('Read timeout Exception')
+            if (data[1] == 0x83) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x83) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x83) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x83) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+
+            myList = list()
+            for i in range(0, quantity):
+                myList.append((data[i * 2 + 3] << 8) + data[i * 2 + 4])
+            return myList
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, quantity_msb, quantity_lsb])
+            self.__tcpClientSocket.send(data)
+            bytes_to_read = 9 + int(quantity * 2)
+            self.__receivedata = bytearray()
+            try:
+                while len(self.__receivedata) == 0:
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+            data = bytearray(self.__receivedata)
+            if (data[1 + 6] == 0x83) & (data[2 + 6] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1 + 6] == 0x83) & (data[2 + 6] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1 + 6] == 0x83) & (data[2 + 6] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1 + 6] == 0x83) & (data[2 + 6] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            myList = list()
+            for i in range(0, quantity):
+                myList.append((data[i * 2 + 3 + 6] << 8) + data[i * 2 + 4 + 6])
+            return myList
+
+    def read_inputregisters(self, starting_address, quantity):
+        """
+        Read Input Registers from Master device (Function code 4)
+        starting_address :  First input register to be read
+        quantity:  Number of input registers to be read
+        returns:  Int Array [0..quantity-1] which contains the input registers
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        if (starting_address > 65535) | (quantity > 125):
+            raise ValueError("Starting address must be 0 - 65535 quantity must be 0 - 125")
+        function_code = 4
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        quantity_lsb = quantity & 0xFF
+        quantity_msb = (quantity & 0xFF00) >> 8
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, quantity_msb,
+                 quantity_lsb, 0, 0])
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data[6] = crcLSB
+            data[7] = crcMSB
+
+            self.__ser.write(data)
+            bytes_to_read = 5 + int(quantity * 2)
+
+            data = self.__ser.read(bytes_to_read)
+
+            b = bytearray(data)
+            data = b
+
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError("Read timeout Exception")
+            if (data[1] == 0x84) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x84) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x84) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x84) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+            myList = list()
+            for i in range(0, quantity):
+                myList.append((data[i * 2 + 3] << 8) + data[i * 2 + 4])
+            return myList
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, quantity_msb, quantity_lsb])
+            self.__tcpClientSocket.send(data)
+            bytes_to_read = 9 + int(quantity * 2)
+            self.__receivedata = bytearray()
+            try:
+                while len(self.__receivedata) == 0:
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+            data = bytearray(self.__receivedata)
+            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1 + 6] == 0x84) & (data[2 + 6] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            myList = list()
+            for i in range(0, quantity):
+                myList.append((data[i * 2 + 3 + 6] << 8) + data[i * 2 + 4 + 6])
+            return myList
+
+    def write_single_coil(self, starting_address, value):
+        """
+        Write single Coil to Master device (Function code 5)
+        starting_address: Coil to be written
+        value:  Coil Value to be written
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        function_code = 5
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        if value:
+            valueLSB = 0x00
+            valueMSB = (0xFF00) >> 8
+        else:
+            valueLSB = 0x00
+            valueMSB = (0x00) >> 8
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, valueMSB, valueLSB,
+                 0, 0])
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data[6] = crcLSB
+            data[7] = crcMSB
+            self.__ser.write(data)
+            bytes_to_read = 8
+            data = self.__ser.read(bytes_to_read)
+            b = bytearray(data)
+            data = b
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError('Read timeout Exception')
+            if (data[1] == 0x85) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x85) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException("Address invalid")
+            if (data[1] == 0x85) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("Value invalid")
+            if (data[1] == 0x85) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+            if data[1] == self.__unitIdentifier:
+                return True
+            else:
+                return False
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, valueMSB, valueLSB])
+            self.__tcpClientSocket.send(data)
+            bytes_to_read = 12
+            self.__receivedata = bytearray()
+            try:
+                while len(self.__receivedata) == 0:
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+            data = bytearray(self.__receivedata)
+            if (data[1 + 6] == 0x85) & (data[2 + 6] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1 + 6] == 0x85) & (data[2 + 6] == 0x02):
+                raise Exceptions.starting_addressInvalidException("Address invalid")
+            if (data[1 + 6] == 0x85) & (data[2 + 6] == 0x03):
+                raise Exceptions.QuantityInvalidException("Value invalid")
+            if (data[1 + 6] == 0x85) & (data[2 + 6] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+
+                return True
+
+    def write_single_register(self, starting_address, value):
+        """
+        Write single Register to Master device (Function code 6)
+        starting_address:  Register to be written
+        value: Register Value to be written
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        function_code = 6
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        valueLSB = value & 0xFF
+        valueMSB = (value & 0xFF00) >> 8
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, valueMSB, valueLSB,
+                 0, 0])
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data[6] = crcLSB
+            data[7] = crcMSB
+            self.__ser.write(data)
+            bytes_to_read = 8
+            data = self.__ser.read(bytes_to_read)
+            b = bytearray(data)
+            data = b
+            # Check for Exception
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError('Read timeout Exception')
+            if (data[1] == 0x86) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x86) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException("Register address invalid")
+            if (data[1] == 0x86) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("Invalid Register Value")
+            if (data[1] == 0x86) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+
+            if data[1] == self.__unitIdentifier:
+                return True
+            else:
+                return False
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, valueMSB, valueLSB])
+            self.__tcpClientSocket.send(data)
+            bytes_to_read = 12
+            self.__receivedata = bytearray()
+            try:
+                while (len(self.__receivedata) == 0):
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+            data = bytearray(self.__receivedata)
+            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x02):
+                raise Exceptions.starting_addressInvalidException("Register address invalid")
+            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x03):
+                raise Exceptions.QuantityInvalidException("Invalid Register Value")
+            if (data[1 + 6] == 0x86) & (data[2 + 6] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+
+                return True
+
+    def write_multiple_coils(self, starting_address, values):
+        """
+        Write multiple coils to Master device (Function code 15)
+        starting_address :  First coil to be written
+        values:  Coil Values [0..quantity-1] to be written
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        function_code = 15
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        quantityLSB = len(values) & 0xFF
+        quantityMSB = (len(values) & 0xFF00) >> 8
+        valueToWrite = list()
+        singleCoilValue = 0
+        for i in range(0, len(values)):
+            if ((i % 8) == 0):
+                if i > 0:
+                    valueToWrite.append(singleCoilValue)
+                singleCoilValue = 0
+
+            if values[i] == True:
+                coilValue = 1
+            else:
+                coilValue = 0
+            singleCoilValue = ((coilValue) << (i % 8) | (singleCoilValue))
+
+        valueToWrite.append(singleCoilValue)
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, quantityMSB,
+                 quantityLSB])
+            data.append(len(valueToWrite))  # Bytecount
+            for i in range(0, len(valueToWrite)):
+                data.append(valueToWrite[i] & 0xFF)
+
+            crc = self.__calculateCRC(data, len(data), 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data.append(crcLSB)
+            data.append(crcMSB)
+            self.__ser.write(data)
+            bytes_to_read = 8
+            data = self.__ser.read(bytes_to_read)
+            b = bytearray(data)
+            data = b
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError('Read timeout Exception')
+            if (data[1] == 0x8F) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x8F) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x8F) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x8F) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+            if data[1] == self.__unitIdentifier:
+                return True
+            else:
+                return False
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, quantityMSB, quantityLSB])
+            data.append(len(valueToWrite))  # Bytecount
+            for i in range(0, len(valueToWrite)):
+                data.append(valueToWrite[i] & 0xFF)
+            self.__tcpClientSocket.send(data)
+            bytes_to_read = 12
+            self.__receivedata = bytearray()
+            try:
+                while (len(self.__receivedata) == 0):
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+            data = bytearray(self.__receivedata)
+            if (data[1] == 0x8F) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x8F) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x8F) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x8F) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+
+            return True
+
+    def write_multiple_registers(self, starting_address, values):
+        """
+        Write multiple registers to Master device (Function code 16)
+        starting_address: First register to be written
+        values:  Register Values [0..quantity-1] to be written
+        """
+        self.__transactionIdentifier += 1
+        if self.__ser is not None:
+            if self.__ser.closed:
+                raise Exception.SerialPortNotOpenedException("serial port not opened")
+        function_code = 16
+        length = 6
+        transaction_identifier_lsb = self.__transactionIdentifier & 0xFF
+        transaction_identifier_msb = ((self.__transactionIdentifier & 0xFF00) >> 8)
+        length_lsb = length & 0xFF
+        length_msb = (length & 0xFF00) >> 8
+        starting_address_lsb = starting_address & 0xFF
+        starting_address_msb = (starting_address & 0xFF00) >> 8
+        quantityLSB = len(values) & 0xFF
+        quantityMSB = (len(values) & 0xFF00) >> 8
+        valueToWrite = list()
+        for i in range(0, len(values)):
+            valueToWrite.append(values[i])
+        if self.__ser is not None:
+            data = bytearray(
+                [self.__unitIdentifier, function_code, starting_address_msb, starting_address_lsb, quantityMSB,
+                 quantityLSB])
+            data.append(len(valueToWrite) * 2)  # Bytecount
+            for i in range(0, len(valueToWrite)):
+                data.append((valueToWrite[i] & 0xFF00) >> 8)
+                data.append(valueToWrite[i] & 0xFF)
+            crc = self.__calculateCRC(data, len(data), 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            data.append(crcLSB)
+            data.append(crcMSB)
+            self.__ser.write(data)
+            bytes_to_read = 8
+            data = self.__ser.read(bytes_to_read)
+            b = bytearray(data)
+            data = b
+            if len(data) < bytes_to_read:
+                raise Exceptions.TimeoutError('Read timeout Exception')
+            if (data[1] == 0x90) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x90) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x90) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x90) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            crc = self.__calculateCRC(data, len(data) - 2, 0)
+            crcLSB = crc & 0xFF
+            crcMSB = (crc & 0xFF00) >> 8
+            if (crcLSB != data[len(data) - 2]) & (crcMSB != data[len(data) - 1]):
+                raise Exceptions.CRCCheckFailedException("CRC check failed")
+            if data[1] == self.__unitIdentifier:
+                return True
+            else:
+                return False
+        else:
+            protocolIdentifierLSB = 0x00
+            protocolIdentifierMSB = 0x00
+            length_lsb = 0x06
+            length_msb = 0x00
+            data = bytearray(
+                [transaction_identifier_msb, transaction_identifier_lsb, protocolIdentifierMSB, protocolIdentifierLSB,
+                 length_msb, length_lsb, self.__unitIdentifier, function_code, starting_address_msb,
+                 starting_address_lsb, quantityMSB, quantityLSB])
+            data.append(len(valueToWrite) * 2)  # Bytecount
+            for i in range(0, len(valueToWrite)):
+                data.append((valueToWrite[i] & 0xFF00) >> 8)
+                data.append(valueToWrite[i] & 0xFF)
+
+            self.__tcpClientSocket.send(data)
+            bytes_to_read = 12
+            self.__receivedata = bytearray()
+            try:
+                while len(self.__receivedata) == 0:
+                    pass
+            except Exception:
+                raise Exception('Read Timeout')
+            data = bytearray(self.__receivedata)
+            if (data[1] == 0x90) & (data[2] == 0x01):
+                raise Exceptions.function_codeNotSupportedException("Function code not supported by master")
+            if (data[1] == 0x90) & (data[2] == 0x02):
+                raise Exceptions.starting_addressInvalidException(
+                    "Starting address invalid or starting address + quantity invalid")
+            if (data[1] == 0x90) & (data[2] == 0x03):
+                raise Exceptions.QuantityInvalidException("quantity invalid")
+            if (data[1] == 0x90) & (data[2] == 0x04):
+                raise Exceptions.ModbusException("error reading")
+            return True
+
+    def __calculateCRC(self, data, numberOfBytes, startByte):
+        crc = 0xFFFF
+        for x in range(0, numberOfBytes):
+            crc = crc ^ data[x]
+            for _ in range(0, 8):
+                if (crc & 0x0001) != 0:
+                    crc = crc >> 1
+                    crc = crc ^ 0xA001
+                else:
+                    crc = crc >> 1
+        return crc
+
+    @property
+    def port(self):
+        """
+        Gets the Port were the Modbus-TCP Server is reachable (Standard is 502)
+        """
+        return self.__port
+
+    @port.setter
+    def port(self, port):
+        """
+        Sets the Port were the Modbus-TCP Server is reachable (Standard is 502)
+        """
+        self.__port = port
+
+    @property
+    def ipaddress(self):
+        """
+        Gets the IP-Address of the Server to be connected
+        """
+        return self.__ipAddress
+
+    @ipaddress.setter
+    def ipaddress(self, ipAddress):
+        """
+        Sets the IP-Address of the Server to be connected
+        """
+        self.__ipAddress = ipAddress
+
+    @property
+    def unitidentifier(self):
+        """
+        Gets the Unit identifier in case of serial connection (Default = 1)
+        """
+        return self.__unitIdentifier
+
+    @unitidentifier.setter
+    def unitidentifier(self, unitIdentifier):
+        """
+        Sets the Unit identifier in case of serial connection (Default = 1)
+        """
+        self.__unitIdentifier = unitIdentifier
+
+    @property
+    def baudrate(self):
+        """
+        Gets the Baudrate for serial connection (Default = 9600)
+        """
+        return self.__baudrate
+
+    @baudrate.setter
+    def baudrate(self, baudrate):
+        """
+        Sets the Baudrate for serial connection (Default = 9600)
+        """
+        self.__baudrate = baudrate
+
+    @property
+    def parity(self):
+        """
+        Gets the of Parity in case of serial connection
+        """
+        return self.__parity
+
+    @parity.setter
+    def parity(self, parity):
+        """
+        Sets the of Parity in case of serial connection
+        Example modbusClient.Parity = Parity.even
+        """
+        self.__parity = parity
+
+    @property
+    def stopbits(self):
+        """
+        Gets the number of stopbits in case of serial connection
+        """
+        return self.__stopbits
+
+    @stopbits.setter
+    def stopbits(self, stopbits):
+        """
+        Sets the number of stopbits in case of serial connection
+        Example: modbusClient.Stopbits = Stopbits.one
+        """
+        self.__stopbits = stopbits
+
+    @property
+    def timeout(self):
+        """
+        Gets the Timeout
+        """
+        return self.__timeout
+
+    @timeout.setter
+    def timeout(self, timeout):
+        """
+        Sets the Timeout
+        """
+        self.__timeout = timeout
+
+    def is_connected(self):
+        """
+        Returns true if a connection has been established
+        """
+        return self.__connected
+
+
+class Parity():
+    even = 0
+    odd = 1
+    none = 2
+
+
+class Stopbits():
+    one = 0
+    two = 1
+    onePointFive = 2
+
+
+def convert_double_to_two_registers(doubleValue):
+    """
+    Convert 32 Bit Value to two 16 Bit Value to send as Modbus Registers
+    doubleValue: Value to be converted
+    return: 16 Bit Register values int[]
+    """
+    myList = list()
+    myList.append(int(doubleValue & 0x0000FFFF))  # Append Least Significant Word
+    myList.append(int((doubleValue & 0xFFFF0000) >> 16))  # Append Most Significant Word
+    return myList
+
+
+def convert_float_to_two_registers(floatValue):
+    """
+    Convert 32 Bit real Value to two 16 Bit Value to send as Modbus Registers
+    floatValue: Value to be converted
+    return: 16 Bit Register values int[]
+    """
+    myList = list()
+    s = bytearray(struct.pack('<f', floatValue))  # little endian
+    myList.append(s[0] | (s[1] << 8))  # Append Least Significant Word
+    myList.append(s[2] | (s[3] << 8))  # Append Most Significant Word
+
+    return myList
+
+
+def convert_registers_to_double(registers):
+    """
+    Convert two 16 Bit Registers to 32 Bit long value - Used to receive 32 Bit values from Modbus (Modbus Registers are 16 Bit long)
+    registers: 16 Bit Registers
+    return: 32 bit value
+    """
+    returnValue = (int(registers[0]) & 0x0000FFFF) | (int((registers[1]) << 16) & 0xFFFF0000)
+    return returnValue
+
+
+def convert_registers_to_float(registers):
+    """
+    Convert two 16 Bit Registers to 32 Bit real value - Used to receive float values from Modbus (Modbus Registers are 16 Bit long)
+    registers: 16 Bit Registers
+    return: 32 bit value real
+    """
+    b = bytearray(4)
+    b[0] = registers[0] & 0xff
+    b[1] = (registers[0] & 0xff00) >> 8
+    b[2] = (registers[1] & 0xff)
+    b[3] = (registers[1] & 0xff00) >> 8
+    returnValue = struct.unpack('<f', b)  # little Endian
+    return returnValue
+
+
+if __name__ == "__main__":
+    modbus_client = ModbusClient("192.168.178.33", 502)
+    modbus_client.connect()
+    counter = 0
+    while (1):
+        counter = counter + 1
+        modbus_client.unitidentifier = 200
+        modbus_client.write_single_register(1, counter)
+        print(modbus_client.read_holdingregisters(1, 1))
+    modbus_client.close()
diff --git a/TP2/easymodbus/modbusException.py b/TP2/easymodbus/modbusException.py
new file mode 100644
index 0000000..af4d594
--- /dev/null
+++ b/TP2/easymodbus/modbusException.py
@@ -0,0 +1,110 @@
+'''
+Created on 14.09.2016
+
+@author: Stefan Rossmann
+'''
+
+
+class ModbusException(Exception):
+    '''
+    classdocs
+    '''
+
+    def __init__(self, expression, message):
+        """ Exception to be thrown if Modbus Server returns error code "Function Code not executed (0x04)"
+        Attributes:
+            expression -- input expression in which the error occurred
+            message -- explanation of the error
+        """
+        self.expression = expression
+        self.message = message
+
+
+class SerialPortNotOpenedException(ModbusException):
+    '''
+    classdocs
+    '''
+
+    def __init__(self, expression, message):
+        """ Exception to be thrown if serial port is not opened
+        Attributes:
+            expression -- input expression in which the error occurred
+            message -- explanation of the error
+        """
+        self.expression = expression
+        self.message = message
+
+
+class ConnectionException(ModbusException):
+    '''
+    classdocs
+    '''
+
+    def __init__(self, expression, message):
+        """ Exception to be thrown if Connection to Modbus device failed
+        Attributes:
+            expression -- input expression in which the error occurred
+            message -- explanation of the error
+        """
+        self.expression = expression
+        self.message = message
+
+
+class FunctionCodeNotSupportedException(ModbusException):
+    '''
+    classdocs
+    '''
+
+    def __init__(self, expression, message):
+        """ Exception to be thrown if Modbus Server returns error code "Function code not supported"
+        Attributes:
+            expression -- input expression in which the error occurred
+            message -- explanation of the error
+        """
+        self.expression = expression
+        self.message = message
+
+
+class QuantityInvalidException(ModbusException):
+    '''
+    classdocs
+    '''
+
+    def __init__(self, expression, message):
+        """ Exception to be thrown if Modbus Server returns error code "quantity invalid"
+        Attributes:
+            expression -- input expression in which the error occurred
+            message -- explanation of the error
+        """
+        self.expression = expression
+        self.message = message
+
+
+class StartingAddressInvalidException(ModbusException):
+    '''
+    classdocs
+    '''
+
+    def __init__(self, expression, message):
+        """ Exception to be thrown if Modbus Server returns error code "starting adddress and quantity invalid"
+        Attributes:
+            expression -- input expression in which the error occurred
+            message -- explanation of the error
+        """
+        self.expression = expression
+        self.message = message
+
+
+class CRCCheckFailedException(ModbusException):
+    '''
+    classdocs
+    '''
+
+    def __init__(self, expression, message):
+        """ Exception to be thrown if CRC Check failed
+        Attributes:
+            expression -- input expression in which the error occurred
+            message -- explanation of the error
+        """
+        self.expression = expression
+        self.message = message
diff --git a/TP2/easymodbus/run.py b/TP2/easymodbus/run.py
new file mode 100644
index 0000000..84b0e76
--- /dev/null
+++ b/TP2/easymodbus/run.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+'''
+Created on 12.09.2016
+
+@author: Stefan Rossmann
+'''
+
+# @UnresolvedImport
+from easymodbus.modbusClient import *
+# @UnresolvedImport
+    
+modbusClient = ModbusClient('127.0.0.1', 502)
+#modbusClient = ModbusClient('COM4')
+modbusClient.parity = Parity.even
+modbusClient.unitidentifier = 2
+modbusClient.baudrate = 9600
+modbusClient.stopbits = Stopbits.one
+modbusClient.connect()
+discreteInputs = modbusClient.read_discreteinputs(0, 8)
+print (discreteInputs)
+
+holdingRegisters = convert_registers_to_float(modbusClient.read_holdingregisters(0, 2))
+print (holdingRegisters)
+inputRegisters = modbusClient.read_inputregisters(0, 8)
+print (inputRegisters)
+coils = modbusClient.read_coils(0, 8)
+print (coils)
+
+modbusClient.write_single_coil(0, True)
+modbusClient.write_single_register(0, 777)
+modbusClient.write_multiple_coils(0, [True,True,True,True,True,False,True,True])
+modbusClient.write_multiple_registers(0, convert_float_to_two_registers(3.141517))
+modbusClient.close()
\ No newline at end of file
diff --git a/TP2/test5.py b/TP2/test5.py
new file mode 100644
index 0000000..70ef3be
--- /dev/null
+++ b/TP2/test5.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+"""
+Seule Test est à utiliser
+
+@author: chevrier6
+"""
+
+from Armoire5 import *
+#
+# a=Armoire6()
+# a.resetAll()
+# i=0
+# a.setCharge(i)
+# s=a.readMesure(i)
+# print(s)
+#
+# def chenillard():
+#     a=Armoire6()
+#     for i in range(a.nbCharge):
+#         a.setCharge(i)
+#         s=a.readMesure(i)
+#         print(s)
+
+def pprint(mesure):
+    output="U={:.2f} I={:.2f} PA={:.2f} PR={:.2f}"
+    return output.format(mesure[0],mesure[1],mesure[2],mesure[3])
+
+def test(charge):
+
+    a=Armoire5()
+    a.resetAll()
+    print("charge ",charge)
+    a.setCharge(charge)
+    s=a.readMesure(charge)
+    print(pprint(s), "\nS1" ,pprint(a.readSecteur1()),"\nS2", pprint(a.readSecteur2()),"\n")
+    a.setSource2(charge)
+    s=a.readMesure(charge)
+    print(pprint(s), "\nS1" ,pprint(a.readSecteur1()),"\nS2", pprint(a.readSecteur2()),"\n")
+    a.unsetCharge(charge)
+
+#
+# def chenillard2():
+#     a=Armoire6()
+#     a.resetAll()
+#     for i in range(a.nbCharge):
+#         print("charge ",i)
+#         a.setCharge(i)
+#         s=a.readMesure(i)
+#         print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         a.setSource2(i)
+#         s=a.readMesure(i)
+#         print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         a.unsetCharge(i)
+#
+#
+# def chenillard3():
+#     a=Armoire6()
+#     a.resetAll()
+#     for charge in range(a.nbCharge):
+#         print("charge ",charge)
+#         a.setCharge(charge)
+#         u,i,pa,pr=a.readMesure(charge)
+#         u1,i1,pa1,pr1=a.readSecteur1()
+#         u2,i2,pa2,pr2=a.readSecteur2()
+#         print((u,i,pa,pr), "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         print(u-u1,i-i1,pa-pa1,pr-pr1)
+#         print(u-u2,i-i2,pa-pa2,pr-pr2)
+#         a.setSource2(charge)
+#         u,i,pa,pr=a.readMesure(charge)
+#         u1,i1,pa1,pr1=a.readSecteur1()
+#         u2,i2,pa2,pr2=a.readSecteur2()
+#         print((u,i,pa,pr), "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         print(u-u1,i-i1,pa-pa1,pr-pr1)
+#         print(u-u2,i-i2,pa-pa2,pr-pr2)
+#         a.unsetCharge(charge)
+#
+# def chenillard2b():
+#     a=Armoire6()
+#     a.resetAll()
+#     for i in range(a.nbCharge):
+#         print("charge ",i)
+#         a.toggleCharge(i)
+#         s=a.readMesure(i)
+#         print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         a.setSource2(i)
+#         s=a.readMesure(i)
+#         print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         a.unsetCharge(i)
+
+#chenillard2b()
\ No newline at end of file
diff --git a/TP2/test6.py b/TP2/test6.py
new file mode 100644
index 0000000..89615be
--- /dev/null
+++ b/TP2/test6.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+"""
+
+
+@author: chevrier6
+"""
+
+from Armoire6 import *
+#
+# a=Armoire6()
+# a.resetAll()
+# i=0
+# a.setCharge(i)
+# s=a.readMesure(i)
+# print(s)
+#
+# def chenillard():
+#     a=Armoire6()
+#     for i in range(a.nbCharge):
+#         a.setCharge(i)
+#         s=a.readMesure(i)
+#         print(s)
+
+def pprint(mesure):
+    output="U={:.2f} I={:.2f} PA={:.2f} PR={:.2f}"
+    return output.format(mesure[0],mesure[1],mesure[2],mesure[3])
+
+def test(charge):
+
+    a=Armoire6()
+    a.resetAll()
+    print("charge ",charge)
+    a.setCharge(charge)
+    s=a.readMesure(charge)
+    print(pprint(s), "\nS1" ,pprint(a.readSecteur1()),"\nS2", pprint(a.readSecteur2()),"\n")
+    a.setSource2(charge)
+    s=a.readMesure(charge)
+    print(pprint(s), "\nS1" ,pprint(a.readSecteur1()),"\nS2", pprint(a.readSecteur2()),"\n")
+    a.unsetCharge(charge)
+
+
+def chenillard2():
+    a=Armoire6()
+    a.resetAll()
+    for i in range(a.nbCharge):
+        print("charge ",i)
+        a.setCharge(i)
+        s=a.readMesure(i)
+        print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+        a.setSource2(i)
+        s=a.readMesure(i)
+        print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+        a.unsetCharge(i)
+
+#
+# def chenillard3():
+#     a=Armoire6()
+#     a.resetAll()
+#     for charge in range(a.nbCharge):
+#         print("charge ",charge)
+#         a.setCharge(charge)
+#         u,i,pa,pr=a.readMesure(charge)
+#         u1,i1,pa1,pr1=a.readSecteur1()
+#         u2,i2,pa2,pr2=a.readSecteur2()
+#         print((u,i,pa,pr), "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         print(u-u1,i-i1,pa-pa1,pr-pr1)
+#         print(u-u2,i-i2,pa-pa2,pr-pr2)
+#         a.setSource2(charge)
+#         u,i,pa,pr=a.readMesure(charge)
+#         u1,i1,pa1,pr1=a.readSecteur1()
+#         u2,i2,pa2,pr2=a.readSecteur2()
+#         print((u,i,pa,pr), "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         print(u-u1,i-i1,pa-pa1,pr-pr1)
+#         print(u-u2,i-i2,pa-pa2,pr-pr2)
+#         a.unsetCharge(charge)
+#
+# def chenillard2b():
+#     a=Armoire6()
+#     a.resetAll()
+#     for i in range(a.nbCharge):
+#         print("charge ",i)
+#         a.toggleCharge(i)
+#         s=a.readMesure(i)
+#         print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         a.setSource2(i)
+#         s=a.readMesure(i)
+#         print(s, "S1" ,a.readSecteur1(),"S2", a.readSecteur2())
+#         a.unsetCharge(i)
+
+#chenillard2b()
\ No newline at end of file
-- 
GitLab