modulitiz-micro 2.42.0__py311-none-any.whl → 2.44.0__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. modulitiz_micro/ModuloMeteo.py +72 -72
  2. modulitiz_micro/ModuloSeriale.py +70 -70
  3. modulitiz_micro/ModuloTarghe.py +47 -47
  4. modulitiz_micro/database/AbstractDatabaseService.py +13 -13
  5. modulitiz_micro/database/AbstractSql.py +69 -69
  6. modulitiz_micro/database/ModuloSqlOracle.py +19 -19
  7. modulitiz_micro/database/ModuloSqlServer.py +43 -43
  8. modulitiz_micro/database/eccezioni/EccezioneDbNoData.py +6 -6
  9. modulitiz_micro/database/mysql/AbstractBasicMysql.py +114 -114
  10. modulitiz_micro/database/mysql/ModuloMysql.py +163 -163
  11. modulitiz_micro/database/mysql/MysqlCommonConverter.py +47 -47
  12. modulitiz_micro/database/mysql/eccezioni/EccezioneMysqlOffline.py +6 -6
  13. modulitiz_micro/database/sqlite/AbstractBasicSQLite.py +114 -114
  14. modulitiz_micro/database/sqlite/ModuloSQLite.py +82 -82
  15. modulitiz_micro/eccezioni/EccezioneCtrlC.py +7 -7
  16. modulitiz_micro/eccezioni/EccezioneScheduler.py +7 -7
  17. modulitiz_micro/eccezioni/http/EccezioneHttp.py +8 -8
  18. modulitiz_micro/eccezioni/http/EccezioneHttp404.py +7 -7
  19. modulitiz_micro/eccezioni/http/EccezioneHttpGeneric.py +7 -7
  20. modulitiz_micro/files/cache/DatabaseCache.py +91 -91
  21. modulitiz_micro/files/cache/decorators/cacheRam.py +26 -26
  22. modulitiz_micro/files/git/ModuloGit.py +28 -28
  23. modulitiz_micro/files/git/decorators/catchAndRaiseGitExceptions.py +19 -19
  24. modulitiz_micro/files/git/exceptions/EccezioneGit.py +7 -7
  25. modulitiz_micro/gestionedom/GestioneDom.py +44 -44
  26. modulitiz_micro/iot/ModuleIotDevice.py +62 -62
  27. modulitiz_micro/keylogger/EccezioneKeyLogger.py +7 -7
  28. modulitiz_micro/keylogger/ModuloKeylogger.py +73 -73
  29. modulitiz_micro/rete/ModuloNetworking.py +72 -72
  30. modulitiz_micro/rete/ModuloOpenVpn.py +15 -15
  31. modulitiz_micro/rete/email/EmailBean.py +5 -5
  32. modulitiz_micro/rete/email/ModuloEmail.py +90 -90
  33. modulitiz_micro/rete/http/ModuloHttp.py +119 -119
  34. modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +91 -91
  35. modulitiz_micro/rete/http/ModuloHttpUtils.py +69 -69
  36. modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -5
  37. modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +22 -22
  38. modulitiz_micro/rete/http/huawei/fusionsolar/ModuleHuaweiFusionSolar.py +84 -0
  39. modulitiz_micro/rete/http/huawei/fusionsolar/beans/TokenBean.py +28 -0
  40. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceBean.py +6 -0
  41. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataBattery.py +22 -0
  42. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataPowerSensor.py +49 -0
  43. modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataResidentialInverter.py +46 -0
  44. modulitiz_micro/rete/http/huawei/fusionsolar/enums/DevTypeIdEnum.py +21 -0
  45. modulitiz_micro/rete/http/huawei/fusionsolar/exceptions/ExceptionTooManyLogins.py +7 -0
  46. modulitiz_micro/rete/http/huawei/fusionsolar/service/AbstractHuaweiFusionSolar.py +71 -0
  47. modulitiz_micro/rete/ntp/AbstractModuloNtp.py +73 -73
  48. modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -8
  49. modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -35
  50. modulitiz_micro/rete/socketserver/AbstractSocketServer.py +267 -267
  51. modulitiz_micro/rete/ssl/ModuloSsl.py +56 -56
  52. modulitiz_micro/sistema/ModuloEnvVars.py +34 -34
  53. modulitiz_micro/sistema/ModuloSystemPipe.py +67 -67
  54. modulitiz_micro/social/telegram/AbstractModuloTelegram.py +53 -53
  55. modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -26
  56. modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -15
  57. modulitiz_micro/util/scheduler/ModuleScheduler.py +26 -26
  58. {modulitiz_micro-2.42.0.dist-info → modulitiz_micro-2.44.0.dist-info}/METADATA +59 -58
  59. modulitiz_micro-2.44.0.dist-info/RECORD +65 -0
  60. {modulitiz_micro-2.42.0.dist-info → modulitiz_micro-2.44.0.dist-info}/licenses/LICENSE +21 -21
  61. modulitiz_micro-2.42.0.dist-info/RECORD +0 -56
  62. {modulitiz_micro-2.42.0.dist-info → modulitiz_micro-2.44.0.dist-info}/WHEEL +0 -0
  63. {modulitiz_micro-2.42.0.dist-info → modulitiz_micro-2.44.0.dist-info}/top_level.txt +0 -0
@@ -1,91 +1,91 @@
1
- import socket
2
- import time
3
- from urllib.error import URLError
4
-
5
- import requests
6
-
7
- from modulitiz_nano.ModuloFunzioni import ModuloFunzioni
8
- from modulitiz_nano.ModuloStringhe import ModuloStringhe
9
- from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
10
- from modulitiz_nano.files.ModuloLogging import ModuloLogging
11
-
12
-
13
- class ModuloHttpConnectionSafe(object):
14
- """
15
- Utility che serve per gestire eventuali errori di rete e riprova a fare la richiesta in caso di errore
16
- """
17
-
18
- def __init__(self,logger: ModuloLogging|None):
19
- self.__logger=logger
20
-
21
- self.isLoggerEnabled=self.__logger is not None
22
- self.contaTentativi=0
23
- self.nomeFunzChiamanti=[]
24
- self.msgFunzChiamanti=None
25
-
26
- def run(self, retries:int,retriesBeforeNotify: int, funzione, *args,**kwargs):
27
- """
28
- se 'retries' e' = -1 allora continua a provare all'infinito
29
- se 'retriesBeforeNotify' e' = 0 allora in caso di errore di rete notifica subito
30
- """
31
- ritorno = None
32
- while self._buildIf(self.contaTentativi,retries):
33
- try:
34
- ritorno = funzione(*args,**kwargs)
35
- self.contaTentativi = -1
36
- except (EccezioneHttpGeneric,ConnectionError, TimeoutError, URLError,
37
- requests.exceptions.ConnectionError, socket.gaierror) as ex:
38
- # controllo il tipo di errore
39
- ModuloHttpConnectionSafe.__checkCodeExc(ex)
40
- # gestisco l'assenza di connessione
41
- self.contaTentativi += 1
42
- # scrivo un messaggio di avviso
43
- if retriesBeforeNotify == 0 or self.contaTentativi >= retriesBeforeNotify:
44
- self.__buildMsgAndNotify()
45
- ModuloHttpConnectionSafe.__dynamicPauseOrRaiseExc(self.contaTentativi, ex)
46
- self.contaTentativi=0
47
- self.nomeFunzChiamanti.clear()
48
- return ritorno
49
-
50
- @staticmethod
51
- def _buildIf(contaTentativi:int,retries:int)->bool:
52
- return contaTentativi >= 0 and (retries==-1 or contaTentativi<retries)
53
-
54
- def __buildMsgAndNotify(self):
55
- if not self.nomeFunzChiamanti:
56
- self.msgFunzChiamanti="Errore di connessione nella funzione "+ModuloFunzioni.getFunctionName(1)+"()"
57
- i=0
58
- while -1<i<2:
59
- nomeFunz = ModuloFunzioni.getFunctionName(i+2)
60
- if not ModuloStringhe.isEmpty(nomeFunz):
61
- self.msgFunzChiamanti += f", chiamata da {nomeFunz}()"
62
- i+=1
63
- else:
64
- i=-1
65
- msg=self.msgFunzChiamanti+f"; tentativo numero: {self.contaTentativi}"
66
- if self.isLoggerEnabled:
67
- self.__logger.error(msg)
68
- else:
69
- print(msg)
70
-
71
- @staticmethod
72
- def __checkCodeExc(ex: Exception):
73
- try:
74
- codiceErrore = ex.code
75
- except AttributeError:
76
- codiceErrore = 0
77
- if codiceErrore in (404, 500):
78
- raise ex
79
-
80
- @staticmethod
81
- def __dynamicPauseOrRaiseExc(contaTentativi: int, ex: Exception):
82
- if 0 < contaTentativi <= 20:
83
- time.sleep(10)
84
- elif 20 < contaTentativi <= 30:
85
- time.sleep(60)
86
- elif 20 < contaTentativi <= 50:
87
- time.sleep(60 * 2)
88
- elif 50 < contaTentativi <= 100:
89
- time.sleep(60 * 5)
90
- else:
91
- raise ex
1
+ import socket
2
+ import time
3
+ from urllib.error import URLError
4
+
5
+ import requests
6
+
7
+ from modulitiz_nano.ModuloFunzioni import ModuloFunzioni
8
+ from modulitiz_nano.ModuloStringhe import ModuloStringhe
9
+ from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
10
+ from modulitiz_nano.files.ModuloLogging import ModuloLogging
11
+
12
+
13
+ class ModuloHttpConnectionSafe(object):
14
+ """
15
+ Utility che serve per gestire eventuali errori di rete e riprova a fare la richiesta in caso di errore
16
+ """
17
+
18
+ def __init__(self,logger: ModuloLogging|None):
19
+ self.__logger=logger
20
+
21
+ self.isLoggerEnabled=self.__logger is not None
22
+ self.contaTentativi=0
23
+ self.nomeFunzChiamanti=[]
24
+ self.msgFunzChiamanti=None
25
+
26
+ def run(self, retries:int,retriesBeforeNotify: int, funzione, *args,**kwargs):
27
+ """
28
+ se 'retries' e' = -1 allora continua a provare all'infinito
29
+ se 'retriesBeforeNotify' e' = 0 allora in caso di errore di rete notifica subito
30
+ """
31
+ ritorno = None
32
+ while self._buildIf(self.contaTentativi,retries):
33
+ try:
34
+ ritorno = funzione(*args,**kwargs)
35
+ self.contaTentativi = -1
36
+ except (EccezioneHttpGeneric,ConnectionError, TimeoutError, URLError,
37
+ requests.exceptions.ConnectionError, socket.gaierror) as ex:
38
+ # controllo il tipo di errore
39
+ ModuloHttpConnectionSafe.__checkCodeExc(ex)
40
+ # gestisco l'assenza di connessione
41
+ self.contaTentativi += 1
42
+ # scrivo un messaggio di avviso
43
+ if retriesBeforeNotify == 0 or self.contaTentativi >= retriesBeforeNotify:
44
+ self.__buildMsgAndNotify()
45
+ ModuloHttpConnectionSafe.__dynamicPauseOrRaiseExc(self.contaTentativi, ex)
46
+ self.contaTentativi=0
47
+ self.nomeFunzChiamanti.clear()
48
+ return ritorno
49
+
50
+ @staticmethod
51
+ def _buildIf(contaTentativi:int,retries:int)->bool:
52
+ return contaTentativi >= 0 and (retries==-1 or contaTentativi<retries)
53
+
54
+ def __buildMsgAndNotify(self):
55
+ if not self.nomeFunzChiamanti:
56
+ self.msgFunzChiamanti="Errore di connessione nella funzione "+ModuloFunzioni.getFunctionName(1)+"()"
57
+ i=0
58
+ while -1<i<2:
59
+ nomeFunz = ModuloFunzioni.getFunctionName(i+2)
60
+ if not ModuloStringhe.isEmpty(nomeFunz):
61
+ self.msgFunzChiamanti += f", chiamata da {nomeFunz}()"
62
+ i+=1
63
+ else:
64
+ i=-1
65
+ msg=self.msgFunzChiamanti+f"; tentativo numero: {self.contaTentativi}"
66
+ if self.isLoggerEnabled:
67
+ self.__logger.error(msg)
68
+ else:
69
+ print(msg)
70
+
71
+ @staticmethod
72
+ def __checkCodeExc(ex: Exception):
73
+ try:
74
+ codiceErrore = ex.code
75
+ except AttributeError:
76
+ codiceErrore = 0
77
+ if codiceErrore in (404, 500):
78
+ raise ex
79
+
80
+ @staticmethod
81
+ def __dynamicPauseOrRaiseExc(contaTentativi: int, ex: Exception):
82
+ if 0 < contaTentativi <= 20:
83
+ time.sleep(10)
84
+ elif 20 < contaTentativi <= 30:
85
+ time.sleep(60)
86
+ elif 20 < contaTentativi <= 50:
87
+ time.sleep(60 * 2)
88
+ elif 50 < contaTentativi <= 100:
89
+ time.sleep(60 * 5)
90
+ else:
91
+ raise ex
@@ -1,69 +1,69 @@
1
- import json
2
- import random
3
- from urllib.parse import quote_plus
4
- from urllib.parse import unquote_plus
5
-
6
- import requests
7
-
8
- from modulitiz_nano.ModuloStringhe import ModuloStringhe
9
- from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
10
- from modulitiz_nano.files.ModuloLogging import ModuloLogging
11
- from modulitiz_micro.rete.http.ModuloHttp import ModuloHttp
12
- from modulitiz_micro.rete.http.ModuloHttpConnectionSafe import ModuloHttpConnectionSafe
13
- from modulitiz_micro.rete.http.decorators.catchAndRaiseHttpExceptions import catchAndRaiseHttpExceptions
14
-
15
-
16
- class ModuloHttpUtils(object):
17
- @staticmethod
18
- def isUrlAvailable(logger:ModuloLogging|None,url:str,retries:int,ignoreCerts:bool=False) -> bool:
19
- if retries!=0:
20
- connectionSafe=ModuloHttpConnectionSafe(logger)
21
- return connectionSafe.run(retries,0,ModuloHttpUtils.__isUrlAvailable,url,ignoreCerts)
22
- try:
23
- return ModuloHttpUtils.__isUrlAvailable(url,ignoreCerts)
24
- except EccezioneHttpGeneric:
25
- return False
26
-
27
- @staticmethod
28
- @catchAndRaiseHttpExceptions
29
- def __isUrlAvailable(url:str,ignoreCerts:bool) -> bool:
30
- with requests.get(url,stream=True,verify=(not ignoreCerts)) as response:
31
- return response.status_code==ModuloHttp.STATUS_OK
32
-
33
- @staticmethod
34
- def getIpV4() -> str|None:
35
- """
36
- Returns public external IpV4 address.
37
- """
38
- url=random.choice(ModuloHttp.URLS_GET_IPV4)
39
- http=ModuloHttp(url,None)
40
- try:
41
- response=http.doGet(2,False)
42
- except EccezioneHttpGeneric:
43
- return None
44
- if response is None:
45
- return None
46
- return response.responseBody.decode(ModuloStringhe.CODIFICA_UTF8)
47
-
48
- @classmethod
49
- def translate(cls,langFrom:str|None,langTo:str,msg:str) -> str|None:
50
- if langFrom is None:
51
- langFrom="auto"
52
- msg=cls.encodeUrl(msg)
53
- url=f'https://translate.googleapis.com/translate_a/single?client=gtx&sl={langFrom}&tl={langTo}&dt=t&q={msg}'
54
- http=ModuloHttp(url,None)
55
- try:
56
- response=http.doGet(3,False)
57
- except EccezioneHttpGeneric:
58
- return None
59
- responseText=response.responseBody.decode(ModuloStringhe.CODIFICA_UTF8)
60
- result=json.loads(responseText)
61
- output="".join(x[0] for x in result[0])
62
- return output
63
-
64
- @staticmethod
65
- def encodeUrl(url: str) -> str:
66
- return quote_plus(url)
67
- @staticmethod
68
- def decodeUrl(url: str) -> str:
69
- return unquote_plus(url)
1
+ import json
2
+ import random
3
+ from urllib.parse import quote_plus
4
+ from urllib.parse import unquote_plus
5
+
6
+ import requests
7
+
8
+ from modulitiz_nano.ModuloStringhe import ModuloStringhe
9
+ from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
10
+ from modulitiz_nano.files.ModuloLogging import ModuloLogging
11
+ from modulitiz_micro.rete.http.ModuloHttp import ModuloHttp
12
+ from modulitiz_micro.rete.http.ModuloHttpConnectionSafe import ModuloHttpConnectionSafe
13
+ from modulitiz_micro.rete.http.decorators.catchAndRaiseHttpExceptions import catchAndRaiseHttpExceptions
14
+
15
+
16
+ class ModuloHttpUtils(object):
17
+ @staticmethod
18
+ def isUrlAvailable(logger:ModuloLogging|None,url:str,retries:int,ignoreCerts:bool=False) -> bool:
19
+ if retries!=0:
20
+ connectionSafe=ModuloHttpConnectionSafe(logger)
21
+ return connectionSafe.run(retries,0,ModuloHttpUtils.__isUrlAvailable,url,ignoreCerts)
22
+ try:
23
+ return ModuloHttpUtils.__isUrlAvailable(url,ignoreCerts)
24
+ except EccezioneHttpGeneric:
25
+ return False
26
+
27
+ @staticmethod
28
+ @catchAndRaiseHttpExceptions
29
+ def __isUrlAvailable(url:str,ignoreCerts:bool) -> bool:
30
+ with requests.get(url,stream=True,verify=(not ignoreCerts)) as response:
31
+ return response.status_code==ModuloHttp.STATUS_OK
32
+
33
+ @staticmethod
34
+ def getIpV4() -> str|None:
35
+ """
36
+ Returns public external IpV4 address.
37
+ """
38
+ url=random.choice(ModuloHttp.URLS_GET_IPV4)
39
+ http=ModuloHttp(url,None)
40
+ try:
41
+ response=http.doGet(2,False)
42
+ except EccezioneHttpGeneric:
43
+ return None
44
+ if response is None:
45
+ return None
46
+ return response.responseBody.decode(ModuloStringhe.CODIFICA_UTF8)
47
+
48
+ @classmethod
49
+ def translate(cls,langFrom:str|None,langTo:str,msg:str) -> str|None:
50
+ if langFrom is None:
51
+ langFrom="auto"
52
+ msg=cls.encodeUrl(msg)
53
+ url=f'https://translate.googleapis.com/translate_a/single?client=gtx&sl={langFrom}&tl={langTo}&dt=t&q={msg}'
54
+ http=ModuloHttp(url,None)
55
+ try:
56
+ response=http.doGet(3,False)
57
+ except EccezioneHttpGeneric:
58
+ return None
59
+ responseText=response.responseBody.decode(ModuloStringhe.CODIFICA_UTF8)
60
+ result=json.loads(responseText)
61
+ output="".join(x[0] for x in result[0])
62
+ return output
63
+
64
+ @staticmethod
65
+ def encodeUrl(url: str) -> str:
66
+ return quote_plus(url)
67
+ @staticmethod
68
+ def decodeUrl(url: str) -> str:
69
+ return unquote_plus(url)
@@ -1,5 +1,5 @@
1
- class HttpResponseBean(object):
2
- def __init__(self,status:int,responseBody:bytes,responseHeaders:dict):
3
- self.status=status
4
- self.responseBody=responseBody
5
- self.responseHeaders=responseHeaders
1
+ class HttpResponseBean(object):
2
+ def __init__(self,status:int,responseBody:bytes,responseHeaders:dict):
3
+ self.status=status
4
+ self.responseBody=responseBody
5
+ self.responseHeaders=responseHeaders
@@ -1,22 +1,22 @@
1
- import socket
2
- from functools import wraps
3
- from urllib.error import URLError
4
-
5
- import requests
6
-
7
- from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
8
-
9
-
10
- def catchAndRaiseHttpExceptions(funzione):
11
- """
12
- Cattura tutte le eccezioni http di vario tipo e rilancia un'eccezione custom
13
- """
14
-
15
- @wraps(funzione)
16
- def wrapped(*args,**kwargs):
17
- try:
18
- return funzione(*args,**kwargs)
19
- except (ConnectionError,TimeoutError,URLError,
20
- requests.exceptions.ConnectionError,socket.gaierror) as ex:
21
- raise EccezioneHttpGeneric() from ex
22
- return wrapped
1
+ import socket
2
+ from functools import wraps
3
+ from urllib.error import URLError
4
+
5
+ import requests
6
+
7
+ from modulitiz_micro.eccezioni.http.EccezioneHttpGeneric import EccezioneHttpGeneric
8
+
9
+
10
+ def catchAndRaiseHttpExceptions(funzione):
11
+ """
12
+ Cattura tutte le eccezioni http di vario tipo e rilancia un'eccezione custom
13
+ """
14
+
15
+ @wraps(funzione)
16
+ def wrapped(*args,**kwargs):
17
+ try:
18
+ return funzione(*args,**kwargs)
19
+ except (ConnectionError,TimeoutError,URLError,
20
+ requests.exceptions.ConnectionError,socket.gaierror) as ex:
21
+ raise EccezioneHttpGeneric() from ex
22
+ return wrapped
@@ -0,0 +1,84 @@
1
+ from modulitiz_micro.rete.http.huawei.fusionsolar.beans.device.DeviceBean import DeviceBean
2
+ from modulitiz_micro.rete.http.huawei.fusionsolar.beans.device.DeviceDataBattery import DeviceDataBattery
3
+ from modulitiz_micro.rete.http.huawei.fusionsolar.beans.device.DeviceDataPowerSensor import DeviceDataPowerSensor
4
+ from modulitiz_micro.rete.http.huawei.fusionsolar.beans.device.DeviceDataResidentialInverter import DeviceDataResidentialInverter
5
+ from modulitiz_micro.rete.http.huawei.fusionsolar.enums.DevTypeIdEnum import DevTypeIdEnum
6
+ from modulitiz_micro.rete.http.huawei.fusionsolar.service.AbstractHuaweiFusionSolar import AbstractHuaweiFusionSolar
7
+
8
+
9
+ class ModuleHuaweiFusionSolar(AbstractHuaweiFusionSolar):
10
+ """
11
+ Api reference:
12
+ https://support.huawei.com/enterprise/en/doc/EDOC1100465337/3055b7a9/api-reference
13
+ """
14
+ URL_PREFIX="https://eu5.fusionsolar.huawei.com/thirdData/"
15
+ XSRF_TOKEN="XSRF-TOKEN"
16
+
17
+ def __init__(self,*args,**kwargs):
18
+ super().__init__(*args,**kwargs)
19
+ self.__plantCode:str|None=None
20
+ self.__deviceIds:list[DeviceBean]=[]
21
+
22
+ # TODO: @override
23
+ def populate(self):
24
+ super().populate()
25
+ # load data
26
+ self.__plantCode=self.getPlantCode()
27
+ self.__deviceIds=self.getDeviceIds()
28
+
29
+ #
30
+ # plants
31
+ #
32
+ def getPlants(self)->dict:
33
+ return self._makeGenericRequest("stations", {"pageNo": 1})
34
+
35
+ def getPlantCode(self)->str:
36
+ if self.__plantCode is not None:
37
+ return self.__plantCode
38
+ self.__plantCode = self.getPlants()['list'][0]['plantCode']
39
+ return self.__plantCode
40
+
41
+ def getRealtimePlantData(self)->dict:
42
+ return self._makeGenericRequest("getStationRealKpi",{"stationCodes":self.__plantCode})[0]["dataItemMap"]
43
+
44
+ #
45
+ # device
46
+ #
47
+ def getDevices(self)->list:
48
+ return list(self._makeGenericRequest("getDevList",{"stationCodes":self.__plantCode}))
49
+
50
+ def getDeviceIds(self)->list[DeviceBean]:
51
+ if self.__deviceIds:
52
+ return self.__deviceIds
53
+ self.__deviceIds = [DeviceBean(x["id"],x["devTypeId"]) for x in self.getDevices()]
54
+ return self.__deviceIds
55
+
56
+ #
57
+ # realtime data
58
+ #
59
+ def getRealtimeDataBattery(self)->DeviceDataBattery:
60
+ return DeviceDataBattery(**self.__getRealtimeDeviceData(DevTypeIdEnum.BATTERY,True))
61
+
62
+ def getRealtimeProductionWh(self) -> int:
63
+ """
64
+ Get total realtime production in Kwh.
65
+ """
66
+ results=self.getRealtimeDataResidentialInverter()
67
+ productionWh=[x.pv1_u*x.pv1_i for x in results]
68
+ return int(sum(productionWh))
69
+
70
+ def getRealtimeDataResidentialInverter(self)->list[DeviceDataResidentialInverter]:
71
+ elems=[]
72
+ for x in self.__getRealtimeDeviceData(DevTypeIdEnum.RESIDENTIAL_INVERTER,False):
73
+ elems.append(DeviceDataResidentialInverter(**x))
74
+ return elems
75
+
76
+ def getRealtimeDataPowerSensor(self)->DeviceDataPowerSensor:
77
+ return DeviceDataPowerSensor(**self.__getRealtimeDeviceData(DevTypeIdEnum.POWER_SENSOR,True))
78
+
79
+ def __getRealtimeDeviceData(self,devTypeId:DevTypeIdEnum,getOnlyFirstResult:bool)->dict|list:
80
+ devIds=",".join([str(x.idDevice) for x in self.__deviceIds if x.idType==devTypeId])
81
+ response=self._makeGenericRequest("getDevRealKpi",{"devIds":devIds,"devTypeId":devTypeId})
82
+ if getOnlyFirstResult:
83
+ return response[0]["dataItemMap"]
84
+ return [x["dataItemMap"] for x in response]
@@ -0,0 +1,28 @@
1
+ from modulitiz_nano.ModuloDate import ModuloDate
2
+
3
+
4
+ class TokenBean(object):
5
+ def __init__(self,value:str):
6
+ self.value=value
7
+ self.dateInsert=ModuloDate.now()
8
+
9
+ @staticmethod
10
+ def fromDict(diz:dict):
11
+ bean=TokenBean(diz["value"])
12
+ bean.dateInsert=ModuloDate.timestampToDate(diz["dateInsert"])
13
+ return bean
14
+
15
+ def toDict(self)->dict:
16
+ return {
17
+ "value":self.value,
18
+ "dateInsert":ModuloDate.dateToTimestamp(self.dateInsert)
19
+ }
20
+
21
+ def isExpired(self)->bool:
22
+ return self.__diffDateInsert()>30
23
+
24
+ def isTooEarly(self)->bool:
25
+ return self.__diffDateInsert()<=2
26
+
27
+ def __diffDateInsert(self)->int:
28
+ return ModuloDate.minutesDiff(ModuloDate.now(),self.dateInsert)
@@ -0,0 +1,6 @@
1
+ from dataclasses import dataclass
2
+
3
+ @dataclass
4
+ class DeviceBean:
5
+ idDevice: int
6
+ idType: int
@@ -0,0 +1,22 @@
1
+ from dataclasses import dataclass
2
+
3
+ @dataclass
4
+ class DeviceDataBattery:
5
+ battery_status: float = 0.0
6
+ max_charge_power: float = 0.0
7
+ max_discharge_power: float = 0.0
8
+
9
+ ch_discharge_power: float = 0.0
10
+ """Instant Kwh given to (+) or taken from (-) battery"""
11
+
12
+ busbar_u: float = 0.0
13
+
14
+ battery_soc: float = 0.0
15
+ """Percentage of battery charge remaining"""
16
+
17
+ battery_soh: float = 0.0
18
+ ch_discharge_model: float = 0.0
19
+ charge_cap: float = 0.0
20
+ discharge_cap: float = 0.0
21
+ rated_capacity: float = 0.0
22
+ run_state: int = 0
@@ -0,0 +1,49 @@
1
+ from dataclasses import dataclass
2
+
3
+ @dataclass
4
+ class DeviceDataPowerSensor:
5
+ meter_status: float = 0.0
6
+ meter_u: float = 0.0
7
+ meter_i: float = 0.0
8
+
9
+ active_power: float = 0.0
10
+ """Instant Kwh given to (+) or taken from (-) grid"""
11
+
12
+ reactive_power: float = 0.0
13
+ power_factor: float = 0.0
14
+ grid_frequency: float = 0.0
15
+ active_cap: float = 0.0
16
+ reverse_active_cap: float = 0.0
17
+ run_state: int = 0
18
+ ab_u: float = 0.0
19
+ bc_u: float = 0.0
20
+ ca_u: float = 0.0
21
+ b_u: float = 0.0
22
+ c_u: float = 0.0
23
+ b_i: float = 0.0
24
+ c_i: float = 0.0
25
+ forward_reactive_cap: float = 0.0
26
+ reverse_reactive_cap: float = 0.0
27
+ active_power_a: float = 0.0
28
+ active_power_b: float = 0.0
29
+ active_power_c: float = 0.0
30
+ reactive_power_a: float = 0.0
31
+ reactive_power_b: float = 0.0
32
+ reactive_power_c: float = 0.0
33
+ total_apparent_power: float = 0.0
34
+ reverse_active_peak: float = 0.0
35
+ reverse_active_power: float = 0.0
36
+ reverse_active_valley: float = 0.0
37
+ reverse_active_top: float = 0.0
38
+ positive_active_peak: float = 0.0
39
+ positive_active_power: float = 0.0
40
+ positive_active_valley: float = 0.0
41
+ positive_active_top: float = 0.0
42
+ reverse_reactive_peak: float = 0.0
43
+ reverse_reactive_power: float = 0.0
44
+ reverse_reactive_valley: float = 0.0
45
+ reverse_reactive_top: float = 0.0
46
+ positive_reactive_peak: float = 0.0
47
+ positive_reactive_power: float = 0.0
48
+ positive_reactive_valley: float = 0.0
49
+ positive_reactive_top: float = 0.0
@@ -0,0 +1,46 @@
1
+ from dataclasses import dataclass
2
+
3
+ @dataclass
4
+ class DeviceDataResidentialInverter:
5
+ inverter_state: float
6
+ ab_u: float
7
+ bc_u: float
8
+ ca_u: float
9
+ a_u: float
10
+ b_u: float
11
+ c_u: float
12
+ a_i: float
13
+ b_i: float
14
+ c_i: float
15
+ efficiency: float
16
+ temperature: float
17
+ power_factor: float
18
+ elec_freq: float
19
+ active_power: float
20
+ reactive_power: float
21
+ day_cap: float
22
+ mppt_power: float
23
+ pv1_u: float
24
+ pv2_u: float
25
+ pv3_u: float
26
+ pv4_u: float
27
+ pv5_u: float
28
+ pv6_u: float
29
+ pv7_u: float
30
+ pv8_u: float
31
+ pv1_i: float
32
+ pv2_i: float
33
+ pv3_i: float
34
+ pv4_i: float
35
+ pv5_i: float
36
+ pv6_i: float
37
+ pv7_i: float
38
+ pv8_i: float
39
+ total_cap: float
40
+ open_time: float
41
+ close_time: float
42
+ mppt_1_cap: float
43
+ mppt_2_cap: float
44
+ mppt_3_cap: float
45
+ mppt_4_cap: float
46
+ run_state: int
@@ -0,0 +1,21 @@
1
+ from enum import IntEnum
2
+ from enum import unique
3
+
4
+
5
+ @unique
6
+ class DevTypeIdEnum(IntEnum):
7
+ STRING_INVERTER=1
8
+ EMI=10
9
+ GRID_METER=17
10
+ RESIDENTIAL_INVERTER=38
11
+ BATTERY=39
12
+ ESS=41
13
+ POWER_SENSOR=47
14
+ MAINS=60001
15
+ GENSET=60003
16
+ SSU_GROUP=60043
17
+ SSU=60044
18
+ POWER_CONVERTER=60092
19
+ LITHIUM_BATTERY_RACK=60014
20
+ AC_OUTPUT_POWER_DISTRIBUTION=60010
21
+
@@ -0,0 +1,7 @@
1
+ from modulitiz_nano.eccezioni.EccezioneBase import EccezioneBase
2
+
3
+
4
+ class ExceptionTooManyLogins(EccezioneBase):
5
+
6
+ def __init__(self,*args,**kwargs):
7
+ super().__init__(*args,**kwargs)