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 zcmYe~<>g{vU|?wHyq|bngn{8Ph=Yt-7#J8F7#J9e-53}cQW&BbQW#U1au`EEG;<D9 zE^`z!BZ$qC!<5Ss#lpzo&XB^I!q&o&!j{U~%pAq$&XB^M!qLKz!qLnW#h$_$%%I6t zWy$4Sl$uzQnxc@Or{J5Pr{GnZr(k5HU}$D#Vqj%#tYBndWWdGckXTxhkzZt`kercP zR+O1qWXAOp<Ty>nTZ~$ojJJ4v^HY*ai=A^aQ}aqR8E;7?=jWBB7L~*orKV>Vm!uXI z$Cu>Cr{&})mL!ApA!8<($3z$y7*ZLc7*iOcm_VLuVTfW*VGd@{WVt2iSXz>wn^=<S zT9KSuP?DLSmkiPdGX}&4VP{bIfP%4xv4$a@A%!8BVI`xVCgUyk+|=UY#Pn26rduq< zsX1vy><kPHD;bJ785kIT**ROqgche3701AR7vqvzoL!P%5K~g1n`CIDTbxo{o}`<b z2=YoyNPtm{V^MB?W>KoCUP0w8j`;Y@yv&mLcwUh8Aa^h@R!L#FSP!PmPm=|tCoeHK zH9r0pSA2YKeoAQ$h|LopUs#%$1Cc4>W?+E05bR6{0rFfCD+2=q56mtOMlc^ESeaqL zdJAi?rm(ayM6p0pNE9n1Wkj*1aHepzFhsGZa-?w2VNBsk;ca1w;!NR7;csDx;z|)n z5o}?I;!Y7t5pH3K;z<!n5p7|J;!P1t5pQ9L;!BZ8k!)dz;!lxEk#1p#5=fCrk!@j! z5=@axk#Av$5=!MrQJBM+qL`x8!V)D6<teAAw6H{pKzXVuYAq~LqEMcCibe}dlvs*p zidG9llz57EicSkdlthYdie3vtlw^v2FoUMSEe=>@Bs0Pi1Oo#Dhz*JhaGEdy<rzqt zV5(t=XG~$PVTfl+VX0w=XHEf$v!t-rFvPQ_u+=ccv!$@tFvPQiQjaEw-%C(Zsp2y< zFwiqM)iX3T)iX3SeF-u-lcAP@;UxzH1H(&BP*j0z)a1Cuk(cD0kyw<TdW$o&z%ivL zwYWI-7H=Yi;hS1qT9kT=3(5`g54t4^WkaNbQ<F<lON$J#3me_yOG!;CEpbdKg4zM+ z2j`a-C8w@rECM+Ql32j50;d>IQUYbKVgXPHF|r{b6B}cdAS?jkNfaY@fl?DVB;_C> z$;iUM%#h8PFHysg#gM`z!H~@u%)rFJ$Pmn+$?R7I3W}E?LX+_pQ(n?aCa|k+F=nDU z>=s9UHpC<Hu=LD;>>ijbM$E$9!^gnDP{Xi*A%$@vBO^G+YcfIX*JQlKQC^f;k{aS4 zR3rn6AaHnq2~eQi;wVZjPAzfF$x*^;H%u1AZcw~~N@93elrYpVWHB}~x-i7@)iTyF zEMTeuyQGi{lzxiX7#J8dnQyTcCFZ547J;JR7FTg<2_&)%i$K0c4-#&$#Sj&$AeVvc zV_@WCtP+986Os}tIIl<r6gptXahK*5r<OpX1dr<=3N-P#4yuIl7F#knH=rabQ1pSk z1rA0FXcU41u2`sqF@>?2u?ZZM3mIyeN|<YyK*f0$i#S6wQ!P^s!vfYCCRk*zWb*r^ zmRFjaT9mH<u}7gGu~;EFKewPLvsfWDucRnd!9XFkM8Qmxtw<5%Pf+Q3i@hi{F$I+S z*osq2oH9#_q(D-jgs_qsoK}lKp1Z|dmY9PcKb-IY(gpb+l$014xfnSZIT!^PtAyZj z1Xo5IpBHI?k`|JmigXwl7;bSS=cFbUq4=ms59Bv+x(5>=7Z<5BFff2h#bOW-$^D2l zhLjTM>I2S_{PgskRDxc(#RE|YNodws;zAT27sx8<>6s!!P|!<*2vFL>8WW&A?u5nl z!f@9k3Jkis9hAI_@VXtTEHm;X&I?9#^@0&7<nem}nu?0S)n@<}PoSqFh)NW1fQm8@ z1{Y_bxP;USDU9F(i)jJVLIy^L8m0xzH4IrSHH-_Hz&uuvXbMvba}HZBdo42~Lk)8Z zOEat%WA%Iajgf%?T$O4v-eN7zNlh(C2UXvohMguy5vU9;5(VXX_T>D$ywv29C{b{I z7hjy2m!6XfZ+jPsgA}nQ=j0cs-eM`q%uOva2bCQxkb+JhB+HYV4{E?CgB$Q*X|!Um z2$X&!LBRuRc``8aFmf>RF>)~RAXnF5>qGp5Q0gR*JK=$2#=yXU6gZ4EjL^Vggal3s z(?U=g&$s{_I3;W~OexHg49$$7UVvW_NOzGeC{Dp`3wA^p6oD#{C}B{k9-o<4P+9`- zcz}IhWC`*lb7o$NCbW15l^0QbV5LE@J_@>*K?Q0O$jgv266$5fDgk)T1lfn~Ur-YP z)Mf-H22hU;)I<U`5>gmN7{nQ1jf4~?afXH9S`Jk2K^hJz%m}d*77#m)C759)t6z~2 z$kT$LrY0yTUqYG{MPeXP36R$Wb25uk!xD2+ON*dQPFS0ZB{3zX2+e1=ct8$^H8rz9 zUWCM|0HXvW+kYlTp8r*dWRI*CC1$Da(;{0?x@3m<OA_QcQ1}%&f>_|H3rv7w1H}hM z`NaFcNR#mv8<s2#@(U<v!LbHv<boQNpqN2zk<>7PQYfU6s||7%C?T$7Mrv7bAz}g= z1x2nPg<z+H39$PGL7@t1@;m337A5ADlz=<|idaZ(TqT8)%21S|6h7p-9F&@hK!XWI z9{AlClA2eXnV(llg!`aMsp396kgJGsUqE7VNoHAU9TDz>Dy541?D4t}TogefEubhB z;=*P$7s_CXVYp%pH-eG|ICX+r>#)>W!?1u6lu9Ax2e>?82Ju1V2Bh=BQsf14D5!ca z@&>VdKm@iZ=RzdO4v<Sh>6C#{gpuh#6C=m}Dnxq(p)MIzxI^nC22l0^@xhJ+b-2I< zA0wpLt6>snsAUE_mw6$mIA?+sYMM-t+z!g<n$Q{vlwWSK<)@_;r<N3fs#CP$tH_;! zfuRTFM39vXOhSxEjzeTWln?~9`a!C}jssN|NVO1C4RRF?&f&GpHB1XwKoxWeYYlTV zV=YS!3#cYSs)xY&2bBFa+0g4DQBVlQXXNLkWagzKY9df2R0MK_CM%@s1^W$D6WwA- zNi0dc#axtHjP6%Zz)S@B6<k6yfhr*o=3qi9AP|0r7XE&kQbi#3MW7+6B2XV0GMWVL z04akKfEtL<01-AI!T>~o`UFMBAQq@iS_JAI6q$m!pt>L2y(j_&Uy%z)44k0ANehvx zd_fYR$SDH38p$W{a<7P=fq?-Oa>by^m4lgsn}eBynS+Icg^!&B201x6IXF02Iav9i zkb{MT6|B=wlj9b9e0)lNa(sLgM^a{qZ(?3%L6mrEVsRy;1)~R{AS02Gcmaj@El&8z jA$Yh9Y#KHP-r}%<49D4l%2jahh=rAdk%y6oS%4J)7P4nZ 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 zcmWIL<>g{vU|^VI_cpd>GXuk85C<8vGB7YWFfcF_Ut(ZjNMVR#NMTH2%3+LR1k+5p z%uy_i5HZ#$R<Iab6dRakk79RcNMTN4X<<lVN#$r}j^cD@NMTK3Yhg%XYi5e#a%V_k zPvK}`Na1K^isDY;OyO!_h~i1%PT^@`h~iD*P2p={h~i7(PZ4Ngh~iHbND<6tDms_S znIe=T+{_dum@2qHXdwg0_9)?0;S>>ZhA80_(Nw{BkyOD2qA4P&!V8%g8B)bk1s8~? zh@^-tWNKz)WGI}KD!4!btdA*}K~t>CkjuF!HL)Z$MIk>=!O%$0z*5i1z|f3~%OSC} zBqP7bN+Gx;H7zkuAt=ANI5#mbkLx8Ufc%m{Br;}(1(g{i14Al96k`fQ6jKUg6mtqw z3UdoX6iW(A3Tq2P6l)4w3VRDf6k7^M3TF#L6nhF+3U>=b6h{hA3U3QT6lV%w3V#bj z6jzEsieL*v6gSAj;Ghvn5d{a0Sc*6}Xe3f3K|zxul_K535G9Z*m?D!R+rrSy7$uY{ zlqH-Z2j>Z<$fqcPWkga%vV>C<;XJ_<r4(hbjA*K8mT-y+oF|x~nxY1l5la=z5>8Qv z^8`~gQZ&Ib;;G_U!YNvCo?wc0iVj#tB2^+wI7JuE6HL)d(Fe;&rb=cBrx?I^DTXOV zEeugoDaOGJnkKh+eDhP1N{gLyGE?(Ps@%C06ciLZa|?1(b5rw55=%1k^Az&a6cQC6 z$`nGJ0~8=?6%zAO5aK~0p$fi<#U-glU=xxVkzxuIQJ{3~4ocTo7#J8z7@8Ss7~&aI z7;6~fnNpZ)7~+{zm}?l~SyEVP7~)yMBwGq=4MRM82}ccMGh+%<31<ys3Zo=L30E_d z14A}bQBw)`0-hAMg^aaK5Sbc=c-|ED8ishj68<cK8ishm5}_>N8isfgh&?q-3q%)! z>}AdKgPO{bjb<*`7A8rC5;2f1MHfoM7l@aLXGxTZXGtyuxswfUmsAa73X>$rJn0mc zU<OUj#7T?{3}D}b!q7QCuehYBG`S?dNFgo12o`>zaMCDFEy_&HQOL>6OVzZ3>&VSV zM1+DZR0AZe^&p`S;b^Ek`}-QIYr-|UWfm2eC<G)HCFZ7<q!uY;7Aurwq$)sd3CJ%h zQGlz3GjO;s#5sT*7a1Cv>lx@7=ozZ(D3}@;;d5IF*m0f#x{fI+MXANbpyUN|Zg6T* zS!$6&NxnjIeqLT`a*0AoKHRmzsmb|yDVTl)dk#r=PG)gQYF;t2)*?_+d<iB%iO|pO z78@jFG8<GG7+x|lFfeG!+~Q2CEJ;l)DoU)pB^8ex+VSy4smZCCWvMBNC5g9G(Bw*r z67z}^lR??UGbJ^zBr`2Dwdj^CnyS*g%n~GNF*NCt%-q!c(vn+3XyV1GMYrV8#7dG2 zAgLfYKRG+K<dy`QJT&Z5Q*JTmq~_h?$}G;zD=taQOHRGTTwGFgi!(E~Ait<2Co}05 zFN7JNo1apelX{B_5-Ok&y(NxjYEoipN>O4->Mgc_#G=fS%3Ca{WvO|$MA4KLKqNVW zOY#enGE0hYG3V!{Vi;BolVuAA=Yw0!nRz9**oq+@Vs~_l_w;iOxy2pq@9Z5P91`T} z=!@aa%mQfYxh0J5hWw%uP3BuH#i==Ix7Z3mnWDG|6!9w=ic}dG7=HOWTg8MHrxq2* zBxj_S6=kLtnZ>xI7H5~_7sQkl=q4E&=@zFHmnZ4wf{U}5kN~5Y)WqUSNcN0@P>?v# zE2zB15g(tKmst`YF9a&x)Ih}^HwPmd0y0T4axro-vN3Wng2Z{4H5i2$xfrWNkyDu- z%oLP@6O=YN85kIxK}Jh3GBDIIWHF>LW^)!DD`8x~l)|)-v6iuhA&WVMIh(0StA;U) z1*9ULHBSpH%971g<WR$y#Re4>0gJL`GZlr@FlMnsL~9tbIKcX|Y8bOP!D3us{TwME z{S7sYS=>-jkbaI7kp3w(j9EMo(Hh1q-WrB1z8Z!s{u%~Q!JEa9#RZbfVohOAVNPM| z1r^F5w+nzo;{|INvV=gsn7~*BGEr!Oa0>fEMn;edp#>lj(He#<u{0)-SPDlCL%ev2 zM3!U?LzWb%(b5YlhNWv5vZNQtfSVPJ!3>(*Rf+Jj!WmM0fC>S4{iF-3x1c3Vei1?# zR2&EAB$lNrlxLP?fJ>(I%(B!xL`hQ&H`foGjKIZ75vWQlVgnT&thd-<`4^PhK$(LB zmcpahEAsOy^3&3y*osPulS_(=SQr=>Lcr-zlj#;)Nn%lYYRN5@#G>?KP1zzI1_p*A zP%<hK2C<|W7#N~>f<ycRoIFE<<Nf_yi?mRMLc;x{#E})m2l#vXg~YpghPf6=fYfpa zI0ku!M8>;@x%w4pf<(BWBK|HeQ7~CQkl8XIJ4HZ*D2U(&Dds6J$}C9@fs{{0ybKHs zpkkr~=3#bdX;Y*K(xC(*_&{nnOEQX56H_wt(r>YafSDLY1*D*kLN7re8gH={mn0UI zXfhQkgUkfwUT~N}2v8m?(qmv?Fac!?Gf<9W0p&0*Mjl282Jzr*CILn^1~vvJ2B!ZU zOk7Mnj694YOl*uoj8!5iIS}d>lne-}H8@}yumIE|2enujN*KZI7p5u)P=YS@DPgW* z$YKJuQnHzf1Yoj|7EKL97HbMaHfIqi@v|;qOJP|EGJ~m5Ae<pjhJ~SoJ&Plot0;?+ z0R&S(?FptxhCHSSh7^Wi22EB!H*ku}{KCk<@REU%fkBh=mJC{%2TE^{0L{!xFJcFU z8OYT|{2&%6A|X-7Qk0rpRwM@!)L>v>Sjh+pUQnrs2-zr(_;`p}!Jyz30|hU*@M2<Q zW8?!DVO)$Ni~^Vi7(^FF_<^ztxBzowKq|mM*_>ekBPaud!VXj%6xl#pf*}3^mJ-%1 zHc$Zo=7H6L!;?J)l-*gX?BLnbIVZn3wO9dCmneWLHywriB2YtB7g9&U+7p@id2mgB zA#R!+;0$+*H5p_8IE0EoDe4wSaYkuLN`84BIH+!M2782t#0R;A2Ni)5cM&MTL4pe$ zaNyKv&cMKs017UU3I=Fu1O*otW0eqUDg#-T3<?uaz=E(i0|NsnXMw}Wh6NNxEZ}0^ zoPmiU9#kkYrZ8o57J-U%#w?~HtrF%1EGf(j8Jieu7*klXS!$S4ShHE27>b-qSX0=V z8JieW*lU?nIBLO_K?<h>LoF*Pou+U(Fr;wXGt{!xuz*F`Ygpi795sw!F;FWTrjDzI z2`t84!vt3cD)hnbnZQ)Es0388u-7oxaMf_u@YHap@TBmhb2Ky7^42gc;Hcp(;jH0p zW=vt1U`XLv$Xv@;!v{8xzlINPo<I$M4Q~pE4MUAU4Q~ps4cNa6xN3O8anF>(Eyj?- zlg&JVu}CY0qXgs<ZfS;QMsbE(!90N!K2(t!hAhSfJT-y~8Ebh<*g$sI3e^bJLfug# zn9VSOu_&vAcL84tKREn&K|P8Tfo!H4-V}C8P}R!h08-Oe!n=S!MG&hR_H2lnO(nbw z1X6^ssu6~&xmLovKrlrFs~S<LnqMWn3xra{z-mYeHALu2GGsG@!VfCKD8T>{abTFh zR1{IdyFfTa9AtWlNHasNaEWLNPYqKulM6$vNv%kY@B*<C@fzL|?i!I4aLA?zi!(?v zK=@(|&5ZU8DU1#b&5WS<n7~w+Q6n78kit_dn!-~nmcmiXp2AbhQNmWkR>N8&RwG)& zQ3GmLAf<_P9!Pq~l2{-KiPaJ|aOo*kgNR+`B90UZ)VRzONa02msgfuGHBY3P8B=(& znI<q7=}llRlnQ6alVf2hVb127z+B`9Dnl6=N|;k5LHPhuj)GIE6xbEKDZG*l(D>$t z$2W6P9ZGzos)58ebI~G{_(oL&iErkjV<_>Bss<9@%tfyd@r@B97Pw+0g#%BlFc<y; z#|mhCMJkaOxfdFgnwX;Cl3AQwlv<Li;F(uYT2ic#R+OI$?W`-Lq?TnSrz&W;mF9ta zF$&4~DX9ub9XN1JoSBy%p9tx$St&ren<+3uGeL%ex@}3R3ZPmaUd9%dCgzo7mQ-3P z_?70S7J>SCa7|E`l;kU*>nchuDJ{w?wo-7)&(BFs%u{d#b;=Z?4fOP22I?BdDwJnr zCTD<3_L9U*P=7BYRRPU#xI4g&HNRhCkp2z0hET}MFHy)ZNX<)4dHMf81H;P;><kRQ zY=c3qj?BDt1*l&Ya!ZR#KrS>;&{Z%qH8nQ1R)9GIMb5~;zyRDFd<kk3zWmPss;fcf zf~#RrE8-=%Rt7cyeu;r21=@yEaIHvAEdcc&Up9eyC#t9s0di+?X#uEKOHENos#Jh< zN`Bd6I5jh`EHNiD1yuFHq73d0ZG@|#%3gwMpkD%T&%lJi4&+TOD#|YcM`mVT`Y!?J zAZLZ-jMU_8g|x)XoYa(;oFJF-fV}~28?KZt0trHDR5oypnsSR1?zdYqkm?!Kx%A5~ z@dt-ILY6BmF{d=u6=W-<^#U3ry(Nv-%1KVlNiNMvEJ<|^at1eTZn1)!r$w@$HYW=x z?cL&n8(Mse2kJJkxwn+kpeZ~al*0Y;OM+p+3fFQ=0Tyzw#O?_RRD=qNKxm@Ikl}|^ z^9ZHl&Oy%3pipxI2O2_x1=LWw#afh@m!5iyEwP{=H815BOHzJ*4!98l>bmBo6oFFC zN^x)t?Un$#yP`N?F?Wj>#b3ABa#HisOEPXrA&pGLXTpaj;&Y0VaLVNtC*9(L=m)EV zu|eV@=uQBuz!c3bPKx4zIS!--i3c)=1w4$xoLrQAi!He**(cZuO#22q-Qooe!4$`r z<i~@fk}>HPTW+OKW^u_a#>`uy1x5KK`N{b?h;bB<UM#}C!A@w+vs=O-1LI-k1GvB{ z&H**oj({3q?0k$|j2w(yi~@`tj4X^Sj9lP$E)OFIBLwp>GBNTnGJ(4gO#fM!#h@}E zc|JxVCIPTI7DkXcpw7M&BMT$be-?1ZAH;{K*8&d$@G%-OvM_;c0bwRa4zRf_AhW?N zrhiQTSy({!LQG}?yGnqOkBJLv9;(@(My45K73ydq7Vpx$$;nvDoWc%ma&o|%oSY5} zDO}JdCrA|3<b;WVnw%gpP?HlT25NGG#6S%_m>B*hCwB@rmL?~U1Vaipw8;rF57gv@ znFncdvg2%Wa)~jda6_A%?BFH{7e<p4E<#b0lLy`eVJyPc<OHeVfi@L!H90|QAWaa) zqH8Ek5Jq@&2c!nl1Ys<~)#M}?YS0EI52S%fLX(plN0SpAjz~>TE}TtH?po0l?pm=F z_FDE7ZVH;5u-HX3Il*p#b|@rK;~S~T$xX1yDTSxWDGlyoaKYmnTay!^1`^-cnw$tV zkod;d<V2`}#5eXPCoD$Lo1Ea#0L4fOJG{w>87s(5PMNCb@U|AXP2ilLnL|t~(-1LD zfL^;;DL|W<$@!T%L^du#O2LDEIGdEDw<*D9!hHv6NfudwMo_Flgbj$W1rc^2!X89` zW^aoeK`c<a58Ns&asqKdZL1<sFaKpDi0cX>Kw~0Bpn0((4-nTAM0kM+Z%`8w)C?-} z0dajngbRr90})9e0zCWxCO~5lx46KiKG?x$hgjXl$i)b%C(-LoXx%0bX<0#s+!4OS zU8VhC9zvrib>RLfQjZzOC<-spqbPhfD5EGT{NO^3R|Gn4LR6LI1s)|40F4{eKt@Rf z!9^ITPs<3cj`G00X5<kNgc@F`nn~bZvoKb3AU$iwqHP#e7Q!4z5yn__3(;#v8CxP4 zD$pv67jKnifoGJ&0MaL~;jIx#;T2(k6pJa`b_{S4QBXlC&Hx=D@c{S5$r&LLUmyV) zA%TvCz+((LVj>BxjwGQYAWTKCCNLFVLm2_#!Z`vW2^|69lVkv`?5N>QK^_6ILWxUM zHITSuE{a2mOH?(GxMVJBLWxUMHITSuE?S0&OI#x$@UUeUXMl`-pocg_6dLNxh1<ZP z4jBOv!59JY$j?au_3MLD(?Ju&Ma0xj#`tO{$QVcl)Yu}ZvG^-0&@f06WE=!tBY|qm zGp~gBVGs<naaLb1YZ(|As%$WZ5{Mo3Ff=lS)LkT1e$Ak|3sL!DsrL|7-byLNutJeP zNMitq2m}#9AObw90<I=OvlZY`fuazQ1ZYg4C=|pB0}<gMA_7E2f`}*(5e*_@KtwEv zhyxMvAObWRUz7-9fjZ$u*eY95a5V%CYFP9a>o77f6z?IYPssx5BXTfuF!3-#`;$xr z`;$zd8d8sunEoWFZwv2B;;(O&FzZ`%kB(NoI3_TLO4Ta@t)3xOuPEN?dGJ)dBA|*E zr6K_LQJ|FoQ{l+0dLeNMt9oH^iCXo-s%KKFUJ<NSFT6sAhB|81%ZE|*f=BulNU3;D za96wv@O~k95KjSC@)BL~qH3dNwTosl&Puna3RLM@6Rva-WA@1PF{sW3_Yz5}b6Y@_ z8KTZbbU5LCO+=krR0C3st<r-Gqk=sO3;5zrva3AAFe<3ZW8z`rU}Pa&<$)I=P`%2- zGJJ~aO_T}`v_1yZMgaBYi^E9jYo@T&GN-UYhe_Gs!=&sE3@IGYVN#GNXqXfx1{x*> ziGhYmVPaf0OhpYToVDC3Y_&Xj9AFk_E%HFAQ3+_ypABhlo->6LK2XYD!&|}unjcT$ zl3+;TgbtK~Yyl0F!fb&Il(IqxO1YuEN=|4Wg`*a<kc)8v7j(Xz6=WWCz8!2fbiQ2! zyiS(~sfytR_aqU6VT?sSCEN>mQ~0o|;eu9G1tr{Q^Y#dH1fXiBlyIZX+auHnLDlRi z;a(t+0_l-5EFd8y5FrMdT?Y?-g8i9-Jl`%>!i_rPU&D~amd!MQsYokDG?*bpESO;e zW1d0^XRUAwXRSyIYb|>UXDvqwD|iN7q(&GzgN_t)@ELTW1;Ws<7q1m8VFk~ki&ROJ zaMUnli8M2&aDwfbG=ZtG4yjMbRI~}+CzL=Mq6DQ65on(f)Dwh+6bF2WlBwtsO01x& zfy4@P5gSUZpsIny3UiSbO01x&fy4@PQ4k_lz~Kby$w^ktffu9UpoM4(#hH2OIjIVu z0Y*@f4_R=IV-DLCcQs-KHz6ri0W^nLl8RUwR0f)hv{Ha50Z&YVtiqxYc{C6_wns#f z3@S2Swt@;+P-$Gn4_(Eo0G)pYcc-d&A-2NAz{Nehpbl|+30@}%8WCJ6io1J+vu8wX zrwCNSA$mb8MZr^%MW9_6w^+epRFnepM=FR&0}<&UA_GKZf`}{-kquf!$N^UF6YLZP zVS#4oK+|tUxgaHZAR-?`fEL&l6@pkLAfgmRfX6q%1bC2B5ENUf@sM;74;t)z2C9J8 zfcji)p#BnQ9uG9LhCGJ{;<JJ0+(0vVe4u%@|LF60EEscmurWz4Mo8ZbG=C?+$il<{ zHVI@V?%6vQ(7YaO<__N5f}6-xC5O_-!tfOC>L!Hr>V^ec-LS%|8#V`q6n1EJ0}=&Q zH!v|!bpsLuRW~p((5xIt3^XeT6GN_S3@|DijuZ|ol?|r^Lkb79vH_U~s%&89K`I*- zXl28NR@tx<S=p$8D;sX4ii8JT*>J*(HO3+@aIwaVRShS!lE?!WYseK6!W@36nn~bd z4S9$Zp+*p@W*fLzgA9=(S2hGg0$SN{A`M$&RyHEw$_7%Efd^^fm5oM<NH7DaAO%-8 z9JRtJ9JL}TEVb+@93)pZVpuC14sc~NVFFWO4N7IR0bbdN<EU&v6+a}T5KHcuiXNcE z3aT1NtS}d`pu`HQ8c3`#7lE1^{3)<lK~)2Z73QJ<M67_r2~^ogRIR{X*}%FkpjrTL zg=2=V!h!dIK*nIHOu$8?6+#uH3V^JS0u>L)H578iLu{SX1}aR!b&dqwL$Fm&u!;uM zEvOQMu53YbN)dW3R0N*H0@XrApoL3C;9)&*K@BFrrL`!?<?zxP)@QI`Vqhp<hPT89 zt*jteRwH#5;3X@ftY)HGS&cd#hSf_b<+UX8f?gAn7W7i9dr-n!16qy_YS42-*|0`E z4`?!>mN$j7mal|8g%ctRUJmM0%U{Ev!Xd^0YDgBHso_uI%w{P%QNz1{qlOPOxdGBs z!&JjB$&kX8%~W(Rg|Sv3k0ph(R-i@zqSKC{hR=zimalLbLKkSd3ABKD0#nf~@B&UQ zM5iR3t(mb_utsnJr~%9iS!4=z6>l>m*i{m>{2=)nUa-Av4v=XU#zLDKh6UU;f+egq zf}p1FLS|6cBL(DR;ToY7m~TbEdWAu*2eU-LEch~EMurrQTF`D2#s$1Jq6-;o1xq+V z=GBVTfJ;3PyG9heZ1_S6-va&=NX;S$UN#IW!vw(#N?{XXUrP8E2td0r=xQL7C`?5X zC4376q05ia)j%4|Ohq;&d<%r2%a763KpM<UMF}N*3xwg_7(_^bCd5D;I-wdNETJI` z4>8z;m<U`1xf`>ugl_?83omGqIoJg?3|U;@68};P7rbT(OW~{)PvNYUfOlg!!QB{% z8gXbh205-l3xUarYvw|Y8ip*<1!AC%CL=?NSgmLYC%E$?UL^r;d5D8j0C;^y!35^Q z7^M1$xo85``Utd;SR9h}u*M~G(E);S$z1e=U|g~kaS)74mLeTQT!KRvQXlO?tB-O^ zb4oG`a#9sQ&0g@(72fK|5KjjPF^&c@3tyE~jM5V-##o0-u!edG-h_gynhJp|i0B8^ zPN1c;MW8CG2=A&0H$=^|QUZ7X2W&0c#12}Y2s}|lUUx`S5~(}H2Clq|iR};F;)bn{ z1g&6%b3jWVdB7%x<b!*=QT&i@4yd;aZVnU`gL+e(peTdz$?QalK<Y49dIEQ&iYI_- z<qLRgWzftN8zT#&5V)_z#mK_M!wBkE2{D1TU4hp~g8Nl`j6#fJOhVvQl8~)fn7u31 zRg9$eu)sDj@-SlWXQ7zQRHcZeuZ8M&l<FI0KaSiWt-hg^Bonlf6sqL|SGY_ye3IY_ zvTzYnwYv&ywaZ__536=lxJ1CZpr*pAUY%M#keV7^kg2dL6<mSxgLe0TMWGdP;SX?i z%wNJ<!w)Kq7czqy1>g!uutor;w^j&jo*>)|AutP49rJ_ODIB%JAeS%Ttr1?xSj%6+ z2{Nx%q(-C`YIcn<xH?{dR2}ofi*WuFP=g;<9UlP~;k@9E9=aOH_!VQ(3vdw*>FA-W zfpjUDig>_9IHXH~t_ISjU@9^I7vZpu9(N7Yweay(ff@lUp&^K@4m_$T1Q$WBj{CsX zF{Gmhb^*LPUIgyIh=NBI3sN|1MN>Fy#n7r_#J(K#>X>jE&?7z#OkgVf1FfhbaVb_S zjI*MSn!sG>hEh>i;jO4aO;gZfR#2l0IhL7=RuPP4=Av^1W0|?=6Tw(!DH21(GC15J z74;EZ6*a8KLquhbxAO>DZ2~imP<0LO-+?O$a;j_rP<4!}%7(0H1P^3R0I4HfV}~GB z*+pHTP1BHl4dB7VqHd5OL=Ghu^?(%jf`~p40jdy-$gBk=&}u<g@D~39)r5zLs0oF@ zD>V@Ho)D<sV-#VeWz7e%LyU>2x{t9+6<^&4_i-|4_!{J45C%1pKzvXP7lRhcq%hX9 zlrW?)L6>m5)w0&G)G*etN-{VyKx9&w!Cf^i@Xk^e2Zj`;Y~~`b8kQ6mdxlz;8kQ7R zkjg?0m`I^UAzuyX%oH}iBJes|@Jd<mnpx1kq)f&I3=Eo#MW7Wqn(UB<7ATUVc=Jkg zlTwTP)0`?xQj4QF!K;QrZ170(EyjvljPYoDKce{J<B>NGMKUum6odBIGcbZSZ16Dh zK^ikmJd9P+D1n8l4`W+1$jRU!0ySGf+iQavG#RTR;YERaY6;{R7SNt2h4R#*RPgBn z5G#<6BgiZU?X*hHNKDE}RnQ17Nz6-0EJ^_#;(~IJ%1Xu}@CJJ<+mCOtfcJ-id<Hr( zf`PS45Mm8<$t*}V87u>eUj_yS5F3QS?gy=&ssU|DX8>=lW<v5qFqQq_S2Pur`=Q(V zr-5=Xc(4defJTgpKw>!vj}RH^&X}Q&?|hjgP!|e(#7t@mT<1zg$SDTc!k06%06JDy zjBs0(7)l_+m5>n92zSFnnq+tT6-`HkX%r{?U=*}`P&5Oy>;U0<B11M59zO8&9GaI| zqJY>@rjVJZkepbY3fkTY-C+qmNda_pl!i-cT4HHViGr;H(rW*ej76YShixnUEk4j; zISAt$5l%+SpQ!3c2z7*?;Gs?hKlv5SM2ZKnFA!VR&?93O0|P?`!e>NAh8JdJI3+?3 z<^dlug*W&u%?u0>1Jo-Si$JRwu*Luf?6jYLgbUG5tAVK?A=D9$hle`3j`u5?jR@+Z zIarDjkk~YY>xm3sN6hfePXnC<lUY)UH<`ortz-lryMirP!KbgxMYyR-7^V1t9Gyf$ zcp}cFfrlrFj&-d_1fBDyfO4V{<a{RuTd247K<7Ncz2{dn7b)OD$H|~4Y>?OzxF^|& z40uG^fR{3mnjT!JK#z+eItD=J=3tEh(CImA;ErQOOVh<rdq{|b26)K8<A7XuLnFfq zH8x-eX(`w$z?gdZd8u$~{fg!xMF_}$=n(=E+YI+Ju@RyKw*ej@(9P6viIt2+;FD#r z)R#q|(`9zUEoDVJXa~CUorG{kI0qii=+5ygnvWC`AP1m_1W4=<!cjyfO+*zP1UZ;M zp`@rZRUs2}BqCBhmyuYkkd&I5r;u7)l9-f}S)75?w9sTM0-XzkElu9y$t;eCnv<Gx z67D>fDoK>$0a=xwrZni(vAo3G)cE*YT=CEY+~VVJ@x;d$mL}#vW!U56Q}UDJ<BQZm zB_!y;q#{EQ3v^gbQ5lF;2_it70E+5CEbzLNb`T3Z9y<xd0xhe*#Zgd{Uyxc<QVDLK zfzHn>DM>8?Hz|rhRT-oV2IYP5302_uFIoW74sO{Y2yhz@)ba!^E-41B%;#WaVc}5X zkmum#;NeK*i06pqh~)_52;s=$i09y8V&r0DVdP>XK(j;TVKiG2$PUm_6=;JOLV=p> zpxt@Jprf%+4-AcBNnws+1)t-{S_C@t2z=-gc%l{D-}TdED_RKh&>|4A7({@^38R?v zQ&OT>^78Xik&+wOzhJL|Ou7JyR8S`Yvbh{=I@wMG%`FmkniOc9n7O1pKZ++mFEt=P zGq1!gvkbcvK_*^9b0SC#C4Yc|6Lbm}xWixsJ;Ae<v4(L0V+m6Y(g`te5he$Q6lQzq zxiK}6Gn?jt3lHb~yt34y5(Q%;1*gms1@IsRXh@@^JYT`k3{|W+6?DdEF?4w*d`cQp z_od{QCgr4p^;;o~fi&(xHb8SA<UkQCnAz~r5%5rZu|j5ENpvjOVc@Rl8&C(7f#F|0 zGeZ$*ctex92t0`Z-WUSfRH6wwI~QSdQ4uIDfMXm?fTI1Dd@{t3@en71jx;DK2OVnw z-F<Wi6y6-5M9Bs^h)j&JXaxfU14@X4oB<DU(4J4wnW?pmC5$CZ3z$LYnJ#2%2A_Po zfTe~Bd=4p73bQ0b3X2_s6L>7Qh7l~oD#=j8l){E86U?B=UbP79X|&iVN=?i`geA#Q zl9rR7SVFxR`Nd?DhLqaD0|cO)1YRbm$qI=X(0IiyHpp44w^#}ile3FJk)_ET#f5MV zIGS!T79-_Sa7@X;VhXGjBcfh_A_~-1VPIop6kwEMlwvAciyl>=%mE)T0o5`k44^C_ z$<WN0!sNgJ=0T&TnK6acfx(FZly!m`G})>SqeKEyc*Bw@c<2zCRdVw4(iOnTRzX)G zv^X^dlx?7=lftqSSQ@syEgy8CtbzulCPCyLg~Xy%SatxJ3F#KVM}si33M9M1@{zHT zLQ-Z4#2sMQLt+R#jsr@y;A~U098?=Kf{$j=WV*!(H~bbi#2j!UL5~e-SZu(RgJJ}d ziN1lN0u;;)Y$}XJ8_**GWHU$>Ttb14Vk==tVQgju9ghjh9VyHX450IRLCea(e9$Nr zt361J4J-!AArLj7gCQ6oImUq@1)_$-h5>xwCT9)fLZ(`#8ql~eSJiQ__hC7RK;(gQ z7C3gWL>@TxL4uTSaR(Z8$^rWTvbG0QI~JksU<ZXNxc&p@xT2MyNM(i`(X$G4=nh+H z9w@_UG8e4_6@%clo9jU=a9Ic@z}ZX+Ys7+m&A`IIPz-7wF|ctk3V=@*6k+6HEZPJz zpCdj#H!(9WKE8_2(9%fH(9A;5(A+}L*f{eWBLf4tdVYBV<S5CaB_L}-1A9?Yh|^m2 zAblJ7**j7EXaYr`HVF8fzao%_iu6IYvgIdbr6!kv8xi2@x(HMug3D-d?gytnumizu zf+${yq4CM!Gqj69Ev;MZ$@!&uphgn7eFSP$-C`{$%FHV%0=KuoZ7^{7AP8_sao9kP z<Fx}tN3jJ10|N^yXf+fE==fM>fqDjH=*7pz$Hu|K!N<YH!4F#b3fe*eK4g|rh!Fts 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