modulitiz-micro 2.43.0__py311-none-any.whl → 2.44.1__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.
- modulitiz_micro/ModuloSeriale.py +70 -70
- modulitiz_micro/ModuloTarghe.py +47 -47
- modulitiz_micro/database/AbstractDatabaseService.py +13 -13
- modulitiz_micro/database/AbstractSql.py +69 -69
- modulitiz_micro/database/ModuloSqlOracle.py +19 -19
- modulitiz_micro/database/ModuloSqlServer.py +43 -43
- modulitiz_micro/database/eccezioni/EccezioneDbNoData.py +6 -6
- modulitiz_micro/database/mysql/AbstractBasicMysql.py +114 -114
- modulitiz_micro/database/mysql/ModuloMysql.py +163 -163
- modulitiz_micro/database/mysql/MysqlCommonConverter.py +47 -47
- modulitiz_micro/database/mysql/eccezioni/EccezioneMysqlOffline.py +6 -6
- modulitiz_micro/database/sqlite/AbstractBasicSQLite.py +114 -114
- modulitiz_micro/database/sqlite/ModuloSQLite.py +82 -82
- modulitiz_micro/eccezioni/EccezioneCtrlC.py +7 -7
- modulitiz_micro/eccezioni/EccezioneScheduler.py +7 -7
- modulitiz_micro/eccezioni/http/EccezioneHttp.py +8 -8
- modulitiz_micro/eccezioni/http/EccezioneHttp404.py +7 -7
- modulitiz_micro/eccezioni/http/EccezioneHttpGeneric.py +7 -7
- modulitiz_micro/files/cache/DatabaseCache.py +91 -91
- modulitiz_micro/files/cache/decorators/cacheRam.py +26 -26
- modulitiz_micro/files/git/ModuloGit.py +28 -28
- modulitiz_micro/files/git/decorators/catchAndRaiseGitExceptions.py +19 -19
- modulitiz_micro/files/git/exceptions/EccezioneGit.py +7 -7
- modulitiz_micro/gestionedom/GestioneDom.py +44 -44
- modulitiz_micro/iot/ModuleIotDevice.py +62 -62
- modulitiz_micro/keylogger/EccezioneKeyLogger.py +7 -7
- modulitiz_micro/keylogger/ModuloKeylogger.py +73 -73
- modulitiz_micro/rete/ModuloNetworking.py +72 -72
- modulitiz_micro/rete/ModuloOpenVpn.py +15 -15
- modulitiz_micro/rete/email/EmailBean.py +5 -5
- modulitiz_micro/rete/email/ModuloEmail.py +90 -90
- modulitiz_micro/rete/http/ModuloHttp.py +119 -119
- modulitiz_micro/rete/http/ModuloHttpConnectionSafe.py +91 -91
- modulitiz_micro/rete/http/ModuloHttpUtils.py +69 -69
- modulitiz_micro/rete/http/beans/HttpResponseBean.py +5 -5
- modulitiz_micro/rete/http/decorators/catchAndRaiseHttpExceptions.py +22 -22
- modulitiz_micro/rete/http/huawei/fusionsolar/ModuleHuaweiFusionSolar.py +84 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/TokenBean.py +28 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceBean.py +6 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataBattery.py +22 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataPowerSensor.py +49 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/beans/device/DeviceDataResidentialInverter.py +46 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/enums/DevTypeIdEnum.py +21 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/exceptions/ExceptionTooManyLogins.py +7 -0
- modulitiz_micro/rete/http/huawei/fusionsolar/service/AbstractHuaweiFusionSolar.py +71 -0
- modulitiz_micro/rete/ntp/AbstractModuloNtp.py +73 -73
- modulitiz_micro/rete/ntp/ModuloNtpIt.py +8 -8
- modulitiz_micro/rete/socketserver/AbstractBasicGetSocketServer.py +35 -35
- modulitiz_micro/rete/socketserver/AbstractSocketServer.py +267 -267
- modulitiz_micro/rete/ssl/ModuloSsl.py +56 -56
- modulitiz_micro/sistema/ModuloEnvVars.py +34 -34
- modulitiz_micro/sistema/ModuloSystemPipe.py +67 -67
- modulitiz_micro/social/telegram/AbstractModuloTelegram.py +53 -53
- modulitiz_micro/social/telegram/ModuloTelegramSimple.py +26 -26
- modulitiz_micro/util/beans/globalvar/AbstractBasicGlobalVarBean.py +15 -15
- modulitiz_micro/util/scheduler/ModuleScheduler.py +26 -26
- modulitiz_micro/weather/AbstractModuleWeather.py +31 -0
- modulitiz_micro/weather/ModuleWeather.py +62 -0
- {modulitiz_micro-2.43.0.dist-info → modulitiz_micro-2.44.1.dist-info}/METADATA +59 -59
- modulitiz_micro-2.44.1.dist-info/RECORD +66 -0
- {modulitiz_micro-2.43.0.dist-info → modulitiz_micro-2.44.1.dist-info}/licenses/LICENSE +21 -21
- modulitiz_micro/ModuloMeteo.py +0 -72
- modulitiz_micro-2.43.0.dist-info/RECORD +0 -56
- {modulitiz_micro-2.43.0.dist-info → modulitiz_micro-2.44.1.dist-info}/WHEEL +0 -0
- {modulitiz_micro-2.43.0.dist-info → modulitiz_micro-2.44.1.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 Wh.
|
65
|
+
"""
|
66
|
+
results=self.getRealtimeDataResidentialInverter()
|
67
|
+
whProductions=[x.pv1_u*x.pv1_i for x in results]
|
68
|
+
return int(sum(whProductions))
|
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,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
|
+
|