Compare commits

...

7 Commits

22 changed files with 1945 additions and 172 deletions

36
.vscode/launch.json vendored
View File

@@ -1,6 +1,7 @@
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{ {
"name": "Python Debugger: Tikmon", "name": "Python Debugger: Tikmon",
"type": "debugpy", "type": "debugpy",
@@ -9,10 +10,9 @@
"console": "integratedTerminal", "console": "integratedTerminal",
"env": { "env": {
"INTERVAL" : "5", "INTERVAL" : "5",
"INFLUXDB_TOKEN":"b46xoZRVsQvyGnv8TVMmTDmxT8LZZsi7O_u776MHIxiE9CPh7yHi0iHMOerUT5o1y65MMxeKKA7S-ijQ3elK-g==", "INFLUXDB_TOKEN":"apiv3_tbEpA8JmIRTfr8Wbw9npD79BcMlFsnV4_jhdt-CdUP53Mos61KBODGaggl2g5oKZZvZrZu3e6mpob6zorhEdbg",
"INFLUXDB_URL" : "http://localhost:8085", "INFLUXDB_URL" : "http://edelweiss-srv:8181",
"INFLUXDB_ORG" : "edelweiss", "INFLUXDB_DATABASE" : "edelweiss",
"INFLUXDB_BUCKET" : "theatre",
"MIKROTIK_IP": "192.168.31.1", "MIKROTIK_IP": "192.168.31.1",
"MIKROTIK_USER": "service", "MIKROTIK_USER": "service",
"MIKROTIK_PASSWORD": "dataservice", "MIKROTIK_PASSWORD": "dataservice",
@@ -29,16 +29,34 @@
"console": "integratedTerminal", "console": "integratedTerminal",
"env": { "env": {
"INTERVAL" : "5", "INTERVAL" : "5",
"INFLUXDB_TOKEN":"rg5dZrBHQxJTH4Etq2jmDduggCC28QaWcua0VVvW4hjsEVhy_JUpVhcyg-aLAbM-TXv92pTB7IGJlyAPvi7Kvw==", "INFLUXDB_TOKEN":"apiv3_tbEpA8JmIRTfr8Wbw9npD79BcMlFsnV4_jhdt-CdUP53Mos61KBODGaggl2g5oKZZvZrZu3e6mpob6zorhEdbg",
"INFLUXDB_URL" : "http://edelweiss-srv:4567", "INFLUXDB_URL" : "http://edelweiss-srv:8181",
"INFLUXDB_ORG" : "edelweiss", "INFLUXDB_DATABASE" : "edelweiss",
"INFLUXDB_BUCKET" : "ups", "PORT": "/dev/ttyS0",
"PORT": "/dev/ttyUSB1",
"BAUD": "2400", "BAUD": "2400",
"LOG_FILE": "/tmp/upsmon.log", "LOG_FILE": "/tmp/upsmon.log",
"LOG_FILE_LVL": "WARNING", "LOG_FILE_LVL": "WARNING",
"LOG_CLI_LVL": "DEBUG" "LOG_CLI_LVL": "DEBUG"
} }
},
{
"name": "Python Debugger: PROJmon",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {
"INTERVAL" : "5",
"INFLUXDB_TOKEN":"apiv3_tbEpA8JmIRTfr8Wbw9npD79BcMlFsnV4_jhdt-CdUP53Mos61KBODGaggl2g5oKZZvZrZu3e6mpob6zorhEdbg",
"INFLUXDB_URL" : "http://edelweiss-srv:8181",
"INFLUXDB_DATABASE" : "edelweiss30d",
"LOG_FILE": "/tmp/upsmon.log",
"LOG_FILE_LVL": "WARNING",
"LOG_CLI_LVL": "DEBUG",
"PROJECTOR_IP":"192.168.31.10",
"PROJECTOR_USER":"alberto",
"PROJECTOR_PASSWORD":"alberto"
}
} }
] ]
} }

15
docker/deploy.sh Executable file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
GIT_HASH=$(git rev-parse --short HEAD)
cp ../pyutils/utils.py ../upsmon/
cp ../pyutils/utils.py ../routermon/
cp ../pyutils/utils.py ../projmon/
docker compose build --build-arg BUILD_VER=${GIT_HASH}
rm ../upsmon/utils.py
rm ../routermon/utils.py
rm ../projmon/utils.py
docker compose up -d

View File

@@ -1,18 +1,30 @@
services: services:
influxdb2: influxdb3:
image: influxdb:2-alpine image: influxdb:3-core
container_name: edx-influxdb container_name: edx-influxdb3
restart: unless-stopped restart: unless-stopped
ulimits:
nofile:
soft: 65536
hard: 65536
ports: ports:
- 8086:8086 - 8181:8181
command:
- influxdb3
- serve
- --node-id=influxb-node0
- --object-store=file
- --data-dir=/var/lib/influxdb3
volumes: volumes:
- type: volume - type: volume
source: influxdb2-data source: influxdb3-data
target: /var/lib/influxdb2 target: /var/lib/influxdb3
- type: volume logging:
source: influxdb2-config driver: "json-file"
target: /etc/influxdb2 options:
max-size: "10m"
max-file: "5"
grafana: grafana:
image: grafana/grafana:latest image: grafana/grafana:latest
container_name: edx-grafana container_name: edx-grafana
@@ -22,49 +34,97 @@ services:
volumes: volumes:
- grafana-data:/var/lib/grafana - grafana-data:/var/lib/grafana
depends_on: depends_on:
- influxdb2 - influxdb3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
upsmon: upsmon:
image: upsmon:latest build:
context: ../upsmon
dockerfile: ../upsmon/upsmon.Dockerfile
args:
BUILD_VER:
#image: upsmon:influx3
container_name: edx-upsmon container_name: edx-upsmon
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- influxdb2 - influxdb3
devices: devices:
- /dev/ttyUSB1:/dev/ttyUSB1 - /dev/ttyS0:/dev/ttyS0
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
environment: environment:
- INTERVAL=5 - INTERVAL=5
- INFLUXDB_TOKEN=b46xoZRVsQvyGnv8TVMmTDmxT8LZZsi7O_u776MHIxiE9CPh7yHi0iHMOerUT5o1y65MMxeKKA7S-ijQ3elK-g== - INFLUXDB_TOKEN=apiv3_tbEpA8JmIRTfr8Wbw9npD79BcMlFsnV4_jhdt-CdUP53Mos61KBODGaggl2g5oKZZvZrZu3e6mpob6zorhEdbg
- INFLUXDB_URL=http://influxdb2:8086 - INFLUXDB_URL=http://influxdb3:8181
- INFLUXDB_ORG=edelweiss - INFLUXDB_DATABASE=edelweiss30d
- INFLUXDB_BUCKET=theatre - PORT=/dev/ttyS0
- PORT=/dev/ttyUSB1
- BAUD=2400 - BAUD=2400
- LOG_FILE=/tmp/upsmon.log - LOG_FILE=/tmp/upsmon.log
- LOG_FILE_LVL=WARNING - LOG_FILE_LVL=WARNING
- LOG_CLI_LVL=INFO - LOG_CLI_LVL=INFO
routermon: routermon:
image: routermon:latest build:
context: ../routermon
dockerfile: ../routermon/routermon.Dockerfile
args:
BUILD_VER:
#image: routermon:influx3
container_name: edx-routermon container_name: edx-routermon
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- influxdb2 - influxdb3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
environment: environment:
- INTERVAL=5 - INTERVAL=5
- INFLUXDB_TOKEN=b46xoZRVsQvyGnv8TVMmTDmxT8LZZsi7O_u776MHIxiE9CPh7yHi0iHMOerUT5o1y65MMxeKKA7S-ijQ3elK-g== - INFLUXDB_TOKEN=apiv3_tbEpA8JmIRTfr8Wbw9npD79BcMlFsnV4_jhdt-CdUP53Mos61KBODGaggl2g5oKZZvZrZu3e6mpob6zorhEdbg
- INFLUXDB_URL=http://influxdb2:8086 - INFLUXDB_URL=http://influxdb3:8181
- INFLUXDB_ORG=edelweiss - INFLUXDB_DATABASE=edelweiss30d
- INFLUXDB_BUCKET=theatre
- MIKROTIK_IP=192.168.31.1 - MIKROTIK_IP=192.168.31.1
- MIKROTIK_USER=service - MIKROTIK_USER=service
- MIKROTIK_PASSWORD=dataservice - MIKROTIK_PASSWORD=dataservice
- LOG_FILE=/tmp/routermon.log - LOG_FILE=/tmp/routermon.log
- LOG_FILE_LVL=WARNING - LOG_FILE_LVL=WARNING
- LOG_CLI_LVL=INFO - LOG_CLI_LVL=INFO
projmon:
build:
context: ../projmon
dockerfile: ../projmon/projmon.Dockerfile
args:
BUILD_VER:
container_name: edx-projmon
restart: unless-stopped
depends_on:
- influxdb3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
environment:
- INTERVAL=5
- INFLUXDB_TOKEN=apiv3_tbEpA8JmIRTfr8Wbw9npD79BcMlFsnV4_jhdt-CdUP53Mos61KBODGaggl2g5oKZZvZrZu3e6mpob6zorhEdbg
- INFLUXDB_URL=http://influxdb3:8181
- INFLUXDB_DATABASE=edelweiss30d
- PROJECTOR_IP=192.168.31.10
- PROJECTOR_USER=alberto
- PROJECTOR_PASSWORD=alberto
- LOG_FILE=/tmp/projmon.log
- LOG_FILE_LVL=WARNING
- LOG_CLI_LVL=INFO
volumes: volumes:
influxdb2-data:
influxdb2-config:
grafana-data: grafana-data:
influxdb3-data:

122
projmon/commands.py Normal file
View File

@@ -0,0 +1,122 @@
from projrequest import ProjectorConnection
from datetime import datetime
from pydantic import BaseModel
from typing import Dict, List, Any
from uuid import UUID
class BaseCommand(BaseModel):
projector: ProjectorConnection
timestamp: datetime
type: str
content: Any
def __init__(self, proj: ProjectorConnection) -> None:
self.projector = proj
pass
def update(self, path: List[str], params: Dict[str, Any] | None = None):
resp = self.projector.get(path=path, params=params)
if resp is not None:
self.timestamp = datetime.fromtimestamp(float(resp['timestamp']))
self.type = resp['type']
self.content = resp['body'][resp['type']]
class DCPInfo(BaseModel):
ID: UUID
Title: str
Path: str
Size: int
ImportTime: datetime
IsImported: bool
VerifyStatus: bool
ValidateStatus: bool
IsPlayable: bool
IsTransferred: bool
class DCPInfoList(BaseCommand):
dcpInfoList: List[DCPInfo]
path: List[str] = ['content', 'dcp', 'info', 'list']
params: Dict[str, str] = { 'formatDate': 'false' }
def get(self):
self.update(path=self.path, params=self.params)
self.dcpInfoList = [DCPInfo(**e) for e in self.content]
class PowerStatus(BaseModel):
Device: str
State: str
class PowerStatusList(BaseCommand):
powerStatusList: List[PowerStatus]
path: List[str] = ['status', 'sms', 'powerstatus']
def get(self):
self.update(path=self.path)
self.powerStatusList = [PowerStatus(**e) for e in self.content]
class ShowStatusDetailClass(BaseModel):
Type: str
Id: UUID
RemainingTime: int
ElapsedTime: int
TotalDuration: int
CurrentEventId: UUID
CurrentEventType: str
IsStoppedByMalfunction: bool
RewindTimeList: str
MalfunctionTime: int
class ShowStatus(BaseCommand):
PlayState: str
ShowStatusDetail: ShowStatusDetailClass
PlayBackMode: str
AtmosPlayingStatus: str
path: List[str] = ['playback', 'showstatus']
def get(self):
self.update(self.path)
self.PlayState = self.content['PlayState']
self.ShowStatusDetail = ShowStatusDetailClass(**self.content['StatusDetail'])
self.PlayBackMode = self.content['PlayBackMode']
self.AtmosPlayingStatus = self.content['AtmosPlayingStatus']
class ImportProgressClass(BaseModel):
TotalBytesToTransfer: int
BytesTransferred: int
PercentCompleted: int
InProgress: int
ImportPath: str
CompletionStatus: str
CompletionTime: str
DCPTitle: str
class ValidationProgressClass(BaseModel):
TotalBytesToValidate: int
BytesValidated: int
PercentCompleted: int
InProgress: bool
Id: UUID
CompletionStatus: str
CompletionTime: datetime
class JobProgress(BaseModel):
Id: int
ValidateAfterImport: bool
AggregatePercentValidated: int
State: str
ImportProgress: ImportProgressClass
ValidationProgressList: List[ValidationProgressClass]
IngestedByFolder: bool
ContentsTransferType: str
class DCPImportJobList(BaseCommand):
IsPaused: bool
JobProgressList: List[JobProgress]
path: List[str] = ['content', 'dcp', 'command']
params: Dict[str, str] = {'action': 'ListImportJobs'}
def get(self):
self.update(self.path)
self.IsPaused = self.content['IsPaused']
self.JobProgressList = [JobProgress(**e) for e in self.content['JobProgressList']]

View File

@@ -0,0 +1,12 @@
FROM python:3.12-alpine
ARG BUILD_VER
RUN apk update && apk upgrade --no-cache
RUN pip install --no-cache-dir influxdb3-python xmltodict requests
COPY ./projmon.py /home/projmon.py
COPY ./utils.py /home/pyutils/utils.py
ENV VER=${BUILD_VER}
CMD [ "python", "/home/projmon.py" ]

91
projmon/projmon.py Normal file
View File

@@ -0,0 +1,91 @@
import os
import sys
import time
import logging
import json
import projrequest as projrequest
from utils import *
from influxdb_client_3 import InfluxDBClient3, Point
# Get environment variables
env = dict(os.environ)
LOGGER: logging.Logger
##################
###### MAIN ######
##################
def main() -> int:
INTERVAL = int(env['INTERVAL'])
try:
# Init InfluxDB-v3 Client
write_client = InfluxDBClient3(host=env['INFLUXDB_URL'],
token=env['INFLUXDB_TOKEN'],
database=env['INFLUXDB_DATABASE'])
except Exception as e:
LOGGER.error(e)
return 1
finally:
LOGGER.info(f"InfluxDB Connected: [{env['INFLUXDB_URL']}/{env['INFLUXDB_DATABASE']}]")
##############################
########## MAIN LOOP #########
##############################
last: float = 0
handler: SignalHandler = SignalHandler(LOGGER)
projector: projrequest.ProjectorConnection = projrequest.ProjectorConnection(
ip=env['PROJECTOR_IP'],
username=env['PROJECTOR_USER'],
password=env['PROJECTOR_PASSWORD']
)
while handler.running:
try:
now:float = time.time()
resp = projector.get(path=['status', 'storage', 'info'], params={"area":"DCP"})
if resp is not None:
print(json.dumps(resp, indent=2))
last: float = time.time()
cycle_time: float = last - now
LOGGER.debug(f"Cycle Time: {cycle_time:4.3f}")
time.sleep(INTERVAL-cycle_time)
except Exception as e:
print(f"Unexpected exception: [{e}]")
return 1
pass
return 0
if __name__ == "__main__":
# Logger Constants
LOG_FORMAT = '%(asctime)s| %(levelname)-7s|%(funcName)-10s|%(lineno)-3d: %(message)-50s'
# Enabling Logger
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG)
LOGGER.propagate = False
formatter = logging.Formatter(LOG_FORMAT, None)
levels = logging.getLevelNamesMapping()
# File logging
log_name = os.path.abspath(env['LOG_FILE'])
fh = logging.FileHandler(log_name)
fh.setLevel(levels[env['LOG_FILE_LVL']])
fh.setFormatter(formatter)
LOGGER.addHandler(fh)
# Console logging
cl = logging.StreamHandler(sys.stdout)
cl.setLevel(levels[env['LOG_CLI_LVL']])
cl.setFormatter(formatter)
LOGGER.addHandler(cl)
LOGGER.warning(f"Routermon started on: {time.asctime()}")
LOGGER.info(f"Routermon BUILD: {env.get("VER", "Test")}")
while main():
LOGGER.error("Main thread exited unexpectedly")
time.sleep(15)
sys.exit(0)

42
projmon/projrequest.py Normal file
View File

@@ -0,0 +1,42 @@
import requests
import xmltodict
from requests.auth import HTTPBasicAuth
from datetime import datetime
from typing import Dict, List, Any
class ProjectorConnection():
ip: str
username: str
password: str
auth: HTTPBasicAuth
def __init__(self, ip: str, username: str, password: str) -> None:
self.ip = ip
self.username = username
self.password = password
self.auth = HTTPBasicAuth(username=self.username, password=self.password)
pass
def get(self, path: List[str], params: Dict[str, str] | None = None) -> Dict[str, Any] | None:
response: requests.Response = requests.get(
url=f"https://{self.ip}/{"/".join(path)}",
params=params,
headers={
"Accept": "application/xml"
},
auth=self.auth,
allow_redirects=False,
timeout=4,
verify=False
)
if response.status_code == 200: # HTTP ok response
rv: dict = {}
content: dict = xmltodict.parse(response.text)["SMSMessage"] # Common containert for all messages
header: dict = content["MessageHeader"]
body: dict = content["MessageBody"]
rv['type'] = header.get("Type", None)
rv['timestamp'] = int(header.get("Timestamp", datetime.now()))
rv['body'] = body[rv["type"]]
return rv
return None

37
projmon/utils.py Normal file
View File

@@ -0,0 +1,37 @@
import signal
from logging import Logger
from influxdb_client_3 import Point
class SignalHandler:
running: bool
logger: Logger
def __init__(self, logger):
self.running: bool = True
self.logger: Logger = logger
signal.signal(signal.SIGINT, self._handle_sigint)
signal.signal(signal.SIGTERM, self._handle_sigint)
def _handle_sigint(self, signum, frame):
self.logger.info(f"Received SIGNAL: {signal.strsignal(signum)}")
self.running = False
def dict2Point(measurement: str, fields: dict, tags: dict | None = None) -> Point:
p = Point(measurement)
for k,v in fields.items():
p.field(k,v)
if tags:
for k,v in tags.items():
p.tag(k,v)
return p
def convertInt(d: dict) -> dict:
for k,v in d.items():
if str.isdecimal(v):
d[k] = int(v)
return d
def convertIntList(l: list[dict]) -> list[dict]:
for n,d in enumerate(l):
l[n] = convertInt(d)
return l

View File

@@ -0,0 +1,897 @@
<?xml version="1.0" encoding="UTF-8"?>
<SMSMessage xmlns="http://xmlns.sony.net/d-cinema/sms/2007b">
<MessageHeader>
<Id>-1</Id>
<Type>DCPInfoList</Type>
<Timestamp>1770199041555</Timestamp>
<Source>LSM-100v2</Source>
</MessageHeader>
<MessageBody>
<DCPInfoList>
<DCPInfo>
<ID>urn:uuid:538469d3-ecdb-41c1-8ebc-845bbe05f6f2</ID>
<Title>ALIGN-4K-V2-4096x2160_TST_MULTI_EN-XX_UK_XX_4K_20120610_MPS_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F538469d3-ecdb-41c1-8ebc-845bbe05f6f2</Path>
<Size>114237784</Size>
<ImportTime>1381739175</ImportTime>
<ImportTimeForFormatDate>2013-10-14T10:26:15.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:1ee6c24d-fa7c-4272-b550-47b5a625ba9c</ID>
<Title>Benvenuti_PRO-1_F-178_IT-XX_20_4K_20250508_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F1ee6c24d-fa7c-4272-b550-47b5a625ba9c</Path>
<Size>2985507624</Size>
<ImportTime>1746817956</ImportTime>
<ImportTimeForFormatDate>2025-05-09T21:12:36.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:8e70a20b-44a1-4cf5-a22e-e8d6b9c7f3ac</ID>
<Title>black_01sec_flat_XSN_F_NS_2K</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F8e70a20b-44a1-4cf5-a22e-e8d6b9c7f3ac</Path>
<Size>55416</Size>
<ImportTime>1414783461</ImportTime>
<ImportTimeForFormatDate>2014-10-31T20:24:21.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:8ce64604-1416-463c-bb4b-6d2793863940</ID>
<Title>Bullone_SHR-1-25_F-178_IT-XX_51_2K_20250411_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F8ce64604-1416-463c-bb4b-6d2793863940</Path>
<Size>1460795010</Size>
<ImportTime>1744381567</ImportTime>
<ImportTimeForFormatDate>2025-04-11T16:26:07.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:4f178d71-ea40-459a-b2c5-99e82f901c65</ID>
<Title>BWV2481_TST-1_F_30_2K_20191225_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F4f178d71-ea40-459a-b2c5-99e82f901c65</Path>
<Size>3035544376</Size>
<ImportTime>1577302386</ImportTime>
<ImportTimeForFormatDate>2019-12-25T20:33:06.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:abe13118-8d9b-4914-8091-ecdaeafad9a1</ID>
<Title>BWV2482_TST-1_F_30_2K_20191225_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fabe13118-8d9b-4914-8091-ecdaeafad9a1</Path>
<Size>3695994429</Size>
<ImportTime>1577302774</ImportTime>
<ImportTimeForFormatDate>2019-12-25T20:39:34.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:2612c2bb-aef8-407b-9b2c-f5191c890835</ID>
<Title>BWV2483_TST-1_F_30_2K_20191225_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F2612c2bb-aef8-407b-9b2c-f5191c890835</Path>
<Size>3697579986</Size>
<ImportTime>1577302968</ImportTime>
<ImportTimeForFormatDate>2019-12-25T20:42:48.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:e1533165-ad13-41b2-a29f-821bf9ab8d79</ID>
<Title>BWV2484_TST-1_F_30_2K_20191226_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fe1533165-ad13-41b2-a29f-821bf9ab8d79</Path>
<Size>2589003736</Size>
<ImportTime>1577441716</ImportTime>
<ImportTimeForFormatDate>2019-12-27T11:15:16.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:d10f7912-3fa3-4462-82d2-be67681f3309</ID>
<Title>BWV2485_TST-1_F_30_2K_20191226_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fd10f7912-3fa3-4462-82d2-be67681f3309</Path>
<Size>2707955856</Size>
<ImportTime>1577441860</ImportTime>
<ImportTimeForFormatDate>2019-12-27T11:17:40.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:3bf39b5c-5d4f-42a8-9e25-16e36cd26137</ID>
<Title>BWV2486_TST-1_F_30_2K_20191226_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F3bf39b5c-5d4f-42a8-9e25-16e36cd26137</Path>
<Size>2893928324</Size>
<ImportTime>1577442013</ImportTime>
<ImportTimeForFormatDate>2019-12-27T11:20:13.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:fef7318c-24c1-417b-b743-8e74cd9837e6</ID>
<Title>ClipStagione25_PRO-1_F-178_IT-XX_20_4K_20250821_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Ffef7318c-24c1-417b-b743-8e74cd9837e6</Path>
<Size>1578149975</Size>
<ImportTime>1758464822</ImportTime>
<ImportTimeForFormatDate>2025-09-21T16:27:02.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:096bbac2-fc75-4a48-bbe9-6053fba6862e</ID>
<Title>DisneyDigital_DLX-51_2D-FramingChart_C-239_EN-XX_INT_51-HI-VI_2K_DI_20160912_DDS_INT_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F096bbac2-fc75-4a48-bbe9-6053fba6862e</Path>
<Size>538152538</Size>
<ImportTime>1571349640</ImportTime>
<ImportTimeForFormatDate>2019-10-18T00:00:40.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:36a35f45-dd98-424a-af59-4253fb5bd93e</ID>
<Title>DisneyDigital_DLX-51_3D-FramingChart_C-239_EN-XX_INT_51-HI-VI_2K_DI_20160912_DDS_INT_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F36a35f45-dd98-424a-af59-4253fb5bd93e</Path>
<Size>929884653</Size>
<ImportTime>1483002512</ImportTime>
<ImportTimeForFormatDate>2016-12-29T10:08:32.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:05a4c195-7998-4a4a-b26b-0df2152e30d9</ID>
<Title>DisneyDigital_DLX-71_2D-FramingChart_C-239_EN-XX_INT_71-HI-VI_2K_DI_20160912_DDS_INT_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F05a4c195-7998-4a4a-b26b-0df2152e30d9</Path>
<Size>518040650</Size>
<ImportTime>1545415354</ImportTime>
<ImportTimeForFormatDate>2018-12-21T19:02:34.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:b11cab29-c9aa-4678-b873-40c7236e785d</ID>
<Title>DisneyDigital_DLX-71_2D-FramingChart_C-239_EN-XX_INT_71-HI-VI_2K_DI_20161006_DTU_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fb11cab29-c9aa-4678-b873-40c7236e785d</Path>
<Size>517960182</Size>
<ImportTime>1571349638</ImportTime>
<ImportTimeForFormatDate>2019-10-18T00:00:38.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:3c9da2c7-e4db-4b44-a170-e77ac9793f3f</ID>
<Title>DisneyDigital_DLX-71_3D-FramingChart_C-239_EN-XX_INT_71-HI-VI_2K_DI_20160912_DDS_INT_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F3c9da2c7-e4db-4b44-a170-e77ac9793f3f</Path>
<Size>898709218</Size>
<ImportTime>1483002532</ImportTime>
<ImportTimeForFormatDate>2016-12-29T10:08:52.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:da67c89e-3d74-4fd7-81ec-4dd3b6580bd6</ID>
<Title>Dolby+-+Digital+Cinema+Flat</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fda67c89e-3d74-4fd7-81ec-4dd3b6580bd6</Path>
<Size>216662075</Size>
<ImportTime>1412963757</ImportTime>
<ImportTimeForFormatDate>2014-10-10T19:55:57.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:ba76434d-4260-4cf1-9df8-c05d93dd09fb</ID>
<Title>Dolby+-+Digital+Cinema+Scope</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fba76434d-4260-4cf1-9df8-c05d93dd09fb</Path>
<Size>209639929</Size>
<ImportTime>1412963719</ImportTime>
<ImportTimeForFormatDate>2014-10-10T19:55:19.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:6c26ced6-a48a-4496-a807-8daf6424348b</ID>
<Title>DOLBY-51-CHANNEL-ID_TST_F_EN-XX_INT_51_2K_20110815_DLB</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F6c26ced6-a48a-4496-a807-8daf6424348b</Path>
<Size>296099915</Size>
<ImportTime>1381738763</ImportTime>
<ImportTimeForFormatDate>2013-10-14T10:19:23.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:fc102b95-5e5c-49bb-9e8d-442c15b135b0</ID>
<Title>EDCF-SMPTE_TST-2-Bv20-24_S_EN-EN_51-HI-VI-Atmos_2K_20170727_DTU_SMPTE_VF</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Ffc102b95-5e5c-49bb-9e8d-442c15b135b0</Path>
<Size>277551986</Size>
<ImportTime>1553632901</ImportTime>
<ImportTimeForFormatDate>2019-03-26T21:41:41.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:52c048c7-9109-425f-b2c7-a73bb14781ad</ID>
<Title>EDCF-SMPTE_TST-2-Bv20-25_S_EN-EN_51-HI-VI-Atmos_2K_20170731_DTU_SMPTE_VF</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F52c048c7-9109-425f-b2c7-a73bb14781ad</Path>
<Size>173678898</Size>
<ImportTime>1553633061</ImportTime>
<ImportTimeForFormatDate>2019-03-26T21:44:21.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:acf4b146-3f36-4d97-b60a-23c62015b478</ID>
<Title>EDCF-SMPTE_TST-2-Bv21-24_S_EN-EN_51-HI-VI_2K_20170630_DTU_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Facf4b146-3f36-4d97-b60a-23c62015b478</Path>
<Size>983119540</Size>
<ImportTime>1553632970</ImportTime>
<ImportTimeForFormatDate>2019-03-26T21:42:50.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:9b5ab3b0-6925-4327-9185-44f600f12c1d</ID>
<Title>EDCF-SMPTE_TST-2-Bv21-25_S_EN-EN_51-HI-VI_2K_20170630_DTU_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F9b5ab3b0-6925-4327-9185-44f600f12c1d</Path>
<Size>895356726</Size>
<ImportTime>1553633042</ImportTime>
<ImportTimeForFormatDate>2019-03-26T21:44:02.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:e30cd293-84cb-4182-8960-9deb61774781</ID>
<Title>Edelweiss+Buoni+prepagati</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fe30cd293-84cb-4182-8960-9deb61774781</Path>
<Size>250859947</Size>
<ImportTime>1421427119</ImportTime>
<ImportTimeForFormatDate>2015-01-16T17:51:59.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:62467524-73cf-4e43-bdb6-11af9279b942</ID>
<Title>Edelweiss+Popcorn</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F62467524-73cf-4e43-bdb6-11af9279b942</Path>
<Size>156258291</Size>
<ImportTime>1389816613</ImportTime>
<ImportTimeForFormatDate>2014-01-15T21:10:13.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:e16cbe98-5e98-416a-982b-e1673c880589</ID>
<Title>Fullscreen+Blue</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fe16cbe98-5e98-416a-982b-e1673c880589</Path>
<Size>8941211</Size>
<ImportTime>1568990341</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:01.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:0396849e-8451-416c-a3a0-3759e1e248dc</ID>
<Title>Fullscreen+Green</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F0396849e-8451-416c-a3a0-3759e1e248dc</Path>
<Size>8958500</Size>
<ImportTime>1568990354</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:14.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:ce637df0-4958-4a5b-8a1f-dc51b8d00857</ID>
<Title>Fullscreen+Red</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fce637df0-4958-4a5b-8a1f-dc51b8d00857</Path>
<Size>8970002</Size>
<ImportTime>1568990347</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:07.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:c15d4dfa-949b-4041-92cb-8e34510ec03f</ID>
<Title>Fullscreen+White</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fc15d4dfa-949b-4041-92cb-8e34510ec03f</Path>
<Size>8949860</Size>
<ImportTime>1568990360</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:20.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:9e2c7c72-e939-4e46-bd8e-21506c129787</ID>
<Title>Generated+by+CineAsset+Version+7.0.8</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F9e2c7c72-e939-4e46-bd8e-21506c129787</Path>
<Size>2480920814</Size>
<ImportTime>1492880638</ImportTime>
<ImportTimeForFormatDate>2017-04-22T19:03:58.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:96d1d128-5521-4dfa-98e7-3108f8e8f328</ID>
<Title>Intervallo</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F96d1d128-5521-4dfa-98e7-3108f8e8f328</Path>
<Size>16887687</Size>
<ImportTime>1381738929</ImportTime>
<ImportTimeForFormatDate>2013-10-14T10:22:09.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:842912b7-769d-4d8c-8817-1d440803af2d</ID>
<Title>ItWasJustAnAcc_FTR-8_F_AR-XX-EN_INT_51_2K_20250606_M14_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F842912b7-769d-4d8c-8817-1d440803af2d</Path>
<Size>103167750929</Size>
<ImportTime>1769960418</ImportTime>
<ImportTimeForFormatDate>2026-02-01T16:40:18.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:abf6bd58-9e5c-4a37-99bb-da6288c53bbc</ID>
<Title>LCDP_FTR_F-185_IT-XX_INT_51_2K_NULL_20250703_IGO_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fabf6bd58-9e5c-4a37-99bb-da6288c53bbc</Path>
<Size>112511530298</Size>
<ImportTime>1769536355</ImportTime>
<ImportTimeForFormatDate>2026-01-27T18:52:35.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:badcf4ff-07a1-4939-8f2d-2dcfee60158c</ID>
<Title>Loghi_PSA-1-25_F-178_XX-XX_20_2K_20240517_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fbadcf4ff-07a1-4939-8f2d-2dcfee60158c</Path>
<Size>2101868561</Size>
<ImportTime>1715975419</ImportTime>
<ImportTimeForFormatDate>2024-05-17T21:50:19.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:3a4869ad-e751-47f6-bd2e-5e5dcae645a8</ID>
<Title>MusicaSottofon_BEETHOVEN-PIANOCONC3_TST-1_S_51_2K_20190205_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F3a4869ad-e751-47f6-bd2e-5e5dcae645a8</Path>
<Size>900785367</Size>
<ImportTime>1549609885</ImportTime>
<ImportTimeForFormatDate>2019-02-08T08:11:25.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:d27961f2-050c-4649-82e0-ec3567c72801</ID>
<Title>MusicaSottofon_DEBUSSY_PRELUDE-APRESMIDI_TST-1_C_51_2K_20190117_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fd27961f2-050c-4649-82e0-ec3567c72801</Path>
<Size>522274165</Size>
<ImportTime>1547756207</ImportTime>
<ImportTimeForFormatDate>2019-01-17T21:16:47.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:aea62ec6-e857-45be-b5c0-f4dbc7249029</ID>
<Title>MusicaSottofon_HAYDN-48_TST-1_C_20_2K_20190106_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Faea62ec6-e857-45be-b5c0-f4dbc7249029</Path>
<Size>605499522</Size>
<ImportTime>1547209477</ImportTime>
<ImportTimeForFormatDate>2019-01-11T13:24:37.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:b228050a-1291-4658-b415-9e5a39b992d4</ID>
<Title>MusicaSottofon_MENDELSSOHN-EBRIDI_TST-1_S_51_2K_20190201_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fb228050a-1291-4658-b415-9e5a39b992d4</Path>
<Size>551565059</Size>
<ImportTime>1549107480</ImportTime>
<ImportTimeForFormatDate>2019-02-02T12:38:00.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:a2fa6893-7967-48f0-824b-fdfcd8e7f4c3</ID>
<Title>MusicaSottofon_Penderecki_TST_FTR-1_F_30_2K_20190921_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fa2fa6893-7967-48f0-824b-fdfcd8e7f4c3</Path>
<Size>446573992</Size>
<ImportTime>1569080559</ImportTime>
<ImportTimeForFormatDate>2019-09-21T17:42:39.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:e4d66535-d3d7-4ec0-b4f7-c0b7524a4253</ID>
<Title>Prefilm_ADV-1_F-178_IT-XX_20_4K_20250920_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fe4d66535-d3d7-4ec0-b4f7-c0b7524a4253</Path>
<Size>1255530989</Size>
<ImportTime>1758398589</ImportTime>
<ImportTimeForFormatDate>2025-09-20T22:03:09.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:da815ea2-4ed2-432e-b4f1-7740d40bb522</ID>
<Title>Prefilm_PRO-1-25_F-178_XX-XX_20_4K_20241226_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fda815ea2-4ed2-432e-b4f1-7740d40bb522</Path>
<Size>1250488416</Size>
<ImportTime>1735253053</ImportTime>
<ImportTimeForFormatDate>2024-12-26T23:44:13.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:a48f1b3a-705b-495d-ab4d-5882df378a47</ID>
<Title>PresentazioneS_PRO-1_F-178_IT-XX_20_4K_20250518_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fa48f1b3a-705b-495d-ab4d-5882df378a47</Path>
<Size>13403353909</Size>
<ImportTime>1748007134</ImportTime>
<ImportTimeForFormatDate>2025-05-23T15:32:14.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:63d83eb5-5b3a-4a83-98d0-019a4af11622</ID>
<Title>PRIMAVERA_FTR_F_IT-EN_IT_51_4K_ST_20251215_FLA_SMPTE_VF2</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F63d83eb5-5b3a-4a83-98d0-019a4af11622</Path>
<Size>2914417</Size>
<ImportTime>1769538385</ImportTime>
<ImportTimeForFormatDate>2026-01-27T19:26:25.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:0e508164-655b-4aba-8113-660e9ef0f463</ID>
<Title>PRIMAVERA_FTR_F_IT-IT-CCAP_IT_51_4K_ST_20251215_FLA_SMPTE_VF4</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F0e508164-655b-4aba-8113-660e9ef0f463</Path>
<Size>2566657</Size>
<ImportTime>1769538487</ImportTime>
<ImportTimeForFormatDate>2026-01-27T19:28:07.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:d231762a-2167-45cc-ae90-95a641cabdc6</ID>
<Title>PRIMAVERA_FTR_F_IT-IT-OCAP_IT_51_4K_ST_20251215_FLA_SMPTE_VF3</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fd231762a-2167-45cc-ae90-95a641cabdc6</Path>
<Size>2953070</Size>
<ImportTime>1769538490</ImportTime>
<ImportTimeForFormatDate>2026-01-27T19:28:10.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:989418bd-cd75-425b-bafe-2db99571e327</ID>
<Title>PRIMAVERA_FTR_F_IT-IT_IT_51-VI-N_4K_ST_20251212_FLA_SMPTE_VF5</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F989418bd-cd75-425b-bafe-2db99571e327</Path>
<Size>7695999568</Size>
<ImportTime>1769538484</ImportTime>
<ImportTimeForFormatDate>2026-01-27T19:28:04.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:a28ababd-ea77-46c3-8e43-c63fdd7af888</ID>
<Title>PRIMAVERA_FTR_F_IT-IT_IT_51_4K_ST_20251215_FLA_SMPTE_VF</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fa28ababd-ea77-46c3-8e43-c63fdd7af888</Path>
<Size>2023628</Size>
<ImportTime>1769536466</ImportTime>
<ImportTimeForFormatDate>2026-01-27T18:54:26.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:db58dfd4-3153-4fca-b2ba-897ec58d61ea</ID>
<Title>PRIMAVERA_FTR_F_IT-IT_IT_71_4K_ST_20251215_FLA_SMPTE_VF1</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fdb58dfd4-3153-4fca-b2ba-897ec58d61ea</Path>
<Size>11527599899</Size>
<ImportTime>1769538382</ImportTime>
<ImportTimeForFormatDate>2026-01-27T19:26:22.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:ba59e26c-6259-4d37-8242-3163918f724e</ID>
<Title>PRIMAVERA_FTR_F_IT-XX_IT_51_4K_ST_20251212_FLA_SMPTE_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fba59e26c-6259-4d37-8242-3163918f724e</Path>
<Size>164598117221</Size>
<ImportTime>1769538380</ImportTime>
<ImportTimeForFormatDate>2026-01-27T19:26:20.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:7ad7d5ed-aaa8-4827-8222-4b62f0d9fef4</ID>
<Title>Prova48fps_TST-1-48_C-178_20_4K_20220622_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F7ad7d5ed-aaa8-4827-8222-4b62f0d9fef4</Path>
<Size>148782597</Size>
<ImportTime>1655959739</ImportTime>
<ImportTimeForFormatDate>2022-06-23T06:48:59.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:08df87ae-9129-49a1-b68b-7796b750e831</ID>
<Title>SempliceInc_FTR_F_AR-IT_INT_51_2K_LR_20251013_64B_IOP_VF</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F08df87ae-9129-49a1-b68b-7796b750e831</Path>
<Size>54918681</Size>
<ImportTime>1769960427</ImportTime>
<ImportTimeForFormatDate>2026-02-01T16:40:27.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:7ef5edfe-223c-4293-813d-30b5282bc845</ID>
<Title>SempliceInc_FTR_F_IT-XX_IT_51_2K_LR_20251023_64B_IOP_VF</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F7ef5edfe-223c-4293-813d-30b5282bc845</Path>
<Size>5772006678</Size>
<ImportTime>1769960432</ImportTime>
<ImportTimeForFormatDate>2026-02-01T16:40:32.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:dab78120-1d16-4d03-8470-bc3b2ff60842</ID>
<Title>SONY+4K+DIGITAL+CINEMA+AD+%28Do+Nov+18+2010%2C+13%3A03%3A51%29</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fdab78120-1d16-4d03-8470-bc3b2ff60842</Path>
<Size>852907458</Size>
<ImportTime>1381739161</ImportTime>
<ImportTimeForFormatDate>2013-10-14T10:26:01.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:8ca146d9-016c-4c7f-bf47-ad5452694bde</ID>
<Title>Sony-4K-Logo-51_ADV_F_EN-XX_51_4K_PRO_20101006_TDC</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F8ca146d9-016c-4c7f-bf47-ad5452694bde</Path>
<Size>259949250</Size>
<ImportTime>1372913958</ImportTime>
<ImportTimeForFormatDate>2013-07-04T06:59:18.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:b8527fd0-3c36-4553-809f-e15d41ca7e8d</ID>
<Title>Sony-4K-Logo-51_ADV_S_EN-XX_51_4K_PRO_20101006_TDC</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fb8527fd0-3c36-4553-809f-e15d41ca7e8d</Path>
<Size>250648071</Size>
<ImportTime>1372913968</ImportTime>
<ImportTimeForFormatDate>2013-07-04T06:59:28.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:0d911c9d-4558-49de-8b45-f9e0d085236d</ID>
<Title>Sony-4K-Logo-71_ADV_F_EN-XX_71_4K_PRO_20101006_TDC</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F0d911c9d-4558-49de-8b45-f9e0d085236d</Path>
<Size>272981250</Size>
<ImportTime>1372913975</ImportTime>
<ImportTimeForFormatDate>2013-07-04T06:59:35.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:87c22684-700a-4cb5-8050-2d65f3d79403</ID>
<Title>Sony-4K-Logo-71_ADV_S_EN-XX_71_4K_PRO_20101006_TDC</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F87c22684-700a-4cb5-8050-2d65f3d79403</Path>
<Size>263680071</Size>
<ImportTime>1372913986</ImportTime>
<ImportTimeForFormatDate>2013-07-04T06:59:46.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:437638a1-8cc0-4868-ab81-bab2aa14f1ac</ID>
<Title>SpongeBob4_FTR-2_F_IT-XX_IT_51_2K_PC_20251008_EKN_SMPTE_VF</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F437638a1-8cc0-4868-ab81-bab2aa14f1ac</Path>
<Size>11087870516</Size>
<ImportTime>1770198056</ImportTime>
<ImportTimeForFormatDate>2026-02-04T10:40:56.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NONE</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:3c95d652-cf6f-4193-a27e-d78112b9d0b8</ID>
<Title>SQV2_TRLSALA_SCOPE</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F3c95d652-cf6f-4193-a27e-d78112b9d0b8</Path>
<Size>3253888227</Size>
<ImportTime>1492720178</ImportTime>
<ImportTimeForFormatDate>2017-04-20T22:29:38.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>OK</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:9e80c783-d0a5-4263-a49d-250dacd1e535</ID>
<Title>Test+Framerate+-+24+fps</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F9e80c783-d0a5-4263-a49d-250dacd1e535</Path>
<Size>34516470</Size>
<ImportTime>1568990375</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:35.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:6ba4786c-24c5-4f8e-bdbe-5ec3de7d22e2</ID>
<Title>Test+Framerate+-+25+fps</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F6ba4786c-24c5-4f8e-bdbe-5ec3de7d22e2</Path>
<Size>37653560</Size>
<ImportTime>1568990381</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:41.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:ae3cf8ff-5be1-403f-aa95-536a613a5be7</ID>
<Title>Test+Framerate+-+30+fps</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fae3cf8ff-5be1-403f-aa95-536a613a5be7</Path>
<Size>45849210</Size>
<ImportTime>1568990391</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:51.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:997d3f4e-826f-491b-b419-7bcec8676c4f</ID>
<Title>Test+Framerate+-+48+fps</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F997d3f4e-826f-491b-b419-7bcec8676c4f</Path>
<Size>71643030</Size>
<ImportTime>1568990398</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:39:58.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:c40ea693-e8b0-4584-a2ce-156873f1280c</ID>
<Title>Test+Framerate+-+50+fps</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Fc40ea693-e8b0-4584-a2ce-156873f1280c</Path>
<Size>75025810</Size>
<ImportTime>1568990405</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:40:05.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:fb4373f1-9bab-4949-8284-f92dd696b250</ID>
<Title>Test+Framerate+-+60+fps</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2Ffb4373f1-9bab-4949-8284-f92dd696b250</Path>
<Size>92311710</Size>
<ImportTime>1568990422</ImportTime>
<ImportTimeForFormatDate>2019-09-20T16:40:22.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:519e50d8-e217-4dab-93a8-461ca4272aa5</ID>
<Title>TotalBlack_XSN-1_C_4K_20181031_IOP_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F519e50d8-e217-4dab-93a8-461ca4272aa5</Path>
<Size>571563558</Size>
<ImportTime>1541152263</ImportTime>
<ImportTimeForFormatDate>2018-11-02T10:51:03.000+01:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>OK</ValidateStatus>
<IsPlayable>false</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:42872b4e-3372-2c4e-bf14-9076e617effe</ID>
<Title>TST+Sony</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F42872b4e-3372-2c4e-bf14-9076e617effe</Path>
<Size>270364250</Size>
<ImportTime>1372913951</ImportTime>
<ImportTimeForFormatDate>2013-07-04T06:59:11.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
<DCPInfo>
<ID>urn:uuid:79f79c12-075a-4433-a290-1b1e71a217df</ID>
<Title>TST+SONY-F65-SAMPLE_TST_S_EN-XX_OV_51_4K_SPE_20110901_SCW_OV</Title>
<Path>%2Fhome%2Fsms%2Fdcp%2F79f79c12-075a-4433-a290-1b1e71a217df</Path>
<Size>13030719583</Size>
<ImportTime>1381739146</ImportTime>
<ImportTimeForFormatDate>2013-10-14T10:25:46.000+02:00</ImportTimeForFormatDate>
<IsImported>true</IsImported>
<VerifyStatus>NG</VerifyStatus>
<ValidateStatus>NONE</ValidateStatus>
<IsPlayable>true</IsPlayable>
<IsTransferred>true</IsTransferred>
</DCPInfo>
</DCPInfoList>
</MessageBody>
</SMSMessage>

View File

@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<SMSMessage xmlns="http://xmlns.sony.net/d-cinema/sms/2007b">
<MessageHeader>
<Id>-1</Id>
<Type>DCPImportJobList</Type>
<Timestamp>1770229557436</Timestamp>
<Source>LSM-100v2</Source>
</MessageHeader>
<MessageBody>
<DCPImportJobList>
<IsPaused>false</IsPaused>
<CurrentJobIdList></CurrentJobIdList>
<JobProgressList>
<JobProgress>
<Id>0</Id>
<ValidateAfterImport>true</ValidateAfterImport>
<AggregatePercentValidated>100</AggregatePercentValidated>
<State>COMPLETE</State>
<ImportProgress>
<TotalBytesToTransfer>11087869580</TotalBytesToTransfer>
<BytesTransferred>11087869580</BytesTransferred>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<ImportPath>ftp%3A%2F192.168.31.16%2FSpongeBob4_FTR-2_F_IT-XX_IT_51_2K_PC_20251008_EKN_SMPTE_VF</ImportPath>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T10:41:02.000+01:00</CompletionTime>
<DCPTitle></DCPTitle>
</ImportProgress>
<ValidationProgressList>
<ValidationProgress>
<TotalBytesToValidate>1</TotalBytesToValidate>
<BytesValidated>1</BytesValidated>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<Id>urn:uuid:437638a1-8cc0-4868-ab81-bab2aa14f1ac</Id>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T10:41:03.000+01:00</CompletionTime>
</ValidationProgress>
</ValidationProgressList>
<IngestedByFolder>true</IngestedByFolder>
<ContentsTransferType>FTPINGEST</ContentsTransferType>
</JobProgress>
<JobProgress>
<Id>1</Id>
<ValidateAfterImport>true</ValidateAfterImport>
<AggregatePercentValidated>100</AggregatePercentValidated>
<State>COMPLETE</State>
<ImportProgress>
<TotalBytesToTransfer>160352519415</TotalBytesToTransfer>
<BytesTransferred>160352519415</BytesTransferred>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<ImportPath>ftp%3A%2F192.168.31.16%2FSpongeBob4_2D_FTR_EN-XX_51-71-ATMOS_SMPTE_OV_AC</ImportPath>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T11:05:36.000+01:00</CompletionTime>
<DCPTitle></DCPTitle>
</ImportProgress>
<ValidationProgressList>
<ValidationProgress>
<TotalBytesToValidate>1</TotalBytesToValidate>
<BytesValidated>1</BytesValidated>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<Id>urn:uuid:bbd72b98-0bae-497e-b587-1e806eb33ff3</Id>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T11:05:37.000+01:00</CompletionTime>
</ValidationProgress>
</ValidationProgressList>
<IngestedByFolder>true</IngestedByFolder>
<ContentsTransferType>FTPINGEST</ContentsTransferType>
</JobProgress>
<JobProgress>
<Id>2</Id>
<ValidateAfterImport>true</ValidateAfterImport>
<AggregatePercentValidated>100</AggregatePercentValidated>
<State>COMPLETE</State>
<ImportProgress>
<TotalBytesToTransfer>1209831989</TotalBytesToTransfer>
<BytesTransferred>1209831989</BytesTransferred>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<ImportPath>ftp%3A%2F192.168.31.25%2FRicercatoriFon_PRO-1-30_F-178_IT-XX_20_2K_20251126_CIN_SMPTE_OV</ImportPath>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T11:05:51.000+01:00</CompletionTime>
<DCPTitle></DCPTitle>
</ImportProgress>
<ValidationProgressList>
<ValidationProgress>
<TotalBytesToValidate>1</TotalBytesToValidate>
<BytesValidated>1</BytesValidated>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<Id>urn:uuid:a34052fe-e763-4212-a836-d209a4211a48</Id>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T11:05:52.000+01:00</CompletionTime>
</ValidationProgress>
</ValidationProgressList>
<IngestedByFolder>true</IngestedByFolder>
<ContentsTransferType>FTPINGEST</ContentsTransferType>
</JobProgress>
<JobProgress>
<Id>3</Id>
<ValidateAfterImport>true</ValidateAfterImport>
<AggregatePercentValidated>100</AggregatePercentValidated>
<State>COMPLETE</State>
<ImportProgress>
<TotalBytesToTransfer>1669076079</TotalBytesToTransfer>
<BytesTransferred>1669076079</BytesTransferred>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<ImportPath>ftp%3A%2F192.168.31.16%2FGOAT_TLR-J_S_IT-XX_IT_51_2K_SPE_20260202_DMK_IOP_OV</ImportPath>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T11:09:00.000+01:00</CompletionTime>
<DCPTitle></DCPTitle>
</ImportProgress>
<ValidationProgressList>
<ValidationProgress>
<TotalBytesToValidate>1</TotalBytesToValidate>
<BytesValidated>1</BytesValidated>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<Id>urn:uuid:03a02548-87d0-4eab-b72b-0fe8a5583e66</Id>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T11:09:01.000+01:00</CompletionTime>
</ValidationProgress>
</ValidationProgressList>
<IngestedByFolder>true</IngestedByFolder>
<ContentsTransferType>FTPINGEST</ContentsTransferType>
</JobProgress>
<JobProgress>
<Id>4</Id>
<ValidateAfterImport>true</ValidateAfterImport>
<AggregatePercentValidated>100</AggregatePercentValidated>
<State>COMPLETE</State>
<ImportProgress>
<TotalBytesToTransfer>171999469124</TotalBytesToTransfer>
<BytesTransferred>171999469124</BytesTransferred>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<ImportPath>ftp%3A%2F192.168.31.15%2FFILM%2FVITA-PRIVATA--IT-IT---FR-IT-</ImportPath>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T18:57:42.135+01:00</CompletionTime>
<DCPTitle>VitaPrivata_FTR_S_FR-IT_IT-IT_IT_51_2K_EUR_20251107_RL1_SMPTE_OV</DCPTitle>
</ImportProgress>
<ValidationProgressList>
<ValidationProgress>
<TotalBytesToValidate>1</TotalBytesToValidate>
<BytesValidated>1</BytesValidated>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<Id>urn:uuid:b91479a6-5558-497d-b044-6bb2b933079c</Id>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T18:57:43.196+01:00</CompletionTime>
</ValidationProgress>
</ValidationProgressList>
<IngestedByFolder>true</IngestedByFolder>
<ContentsTransferType>FTPINGEST</ContentsTransferType>
</JobProgress>
<JobProgress>
<Id>5</Id>
<ValidateAfterImport>true</ValidateAfterImport>
<AggregatePercentValidated>100</AggregatePercentValidated>
<State>COMPLETE</State>
<ImportProgress>
<TotalBytesToTransfer>164279635201</TotalBytesToTransfer>
<BytesTransferred>164279635201</BytesTransferred>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<ImportPath>%2Fmnt%2Fsata%2FAGATA_CHRISTIAN_-_DELITTO_SULLE_NEVI__ITA_</ImportPath>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T19:25:22.668+01:00</CompletionTime>
<DCPTitle>AgataChrist-DSN_FTR-C_S_IT-XX_IT_51_4K_MED_20251230_RL1_IOP_OV</DCPTitle>
</ImportProgress>
<ValidationProgressList>
<ValidationProgress>
<TotalBytesToValidate>1</TotalBytesToValidate>
<BytesValidated>1</BytesValidated>
<PercentCompleted>100</PercentCompleted>
<InProgress>false</InProgress>
<Id>urn:uuid:8031727a-27d2-4f10-b95d-c66ff0e1eb06</Id>
<CompletionStatus>SUCCESSFUL</CompletionStatus>
<CompletionTime>2026-02-04T19:25:23.707+01:00</CompletionTime>
</ValidationProgress>
</ValidationProgressList>
<IngestedByFolder>true</IngestedByFolder>
<ContentsTransferType>INGEST</ContentsTransferType>
</JobProgress>
</JobProgressList>
</DCPImportJobList>
</MessageBody>
</SMSMessage>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<SMSMessage xmlns="http://xmlns.sony.net/d-cinema/sms/2007b">
<MessageHeader>
<Id>-1</Id>
<Type>PowerStatusList</Type>
<Timestamp>1770226327272</Timestamp>
<Source>LSM-100v2</Source>
</MessageHeader>
<MessageBody>
<PowerStatusList>
<PowerStatus>
<Device>SMS</Device>
<State>ON</State>
</PowerStatus>
<PowerStatus>
<Device>CSS</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>MARRIAGE</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>MB</Device>
<State>ON</State>
</PowerStatus>
<PowerStatus>
<Device>RAID</Device>
<State>ON</State>
</PowerStatus>
<PowerStatus>
<Device>PRJ</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>ENCLOSURE</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>UPS</Device>
<State>ON</State>
</PowerStatus>
</PowerStatusList>
</MessageBody>
</SMSMessage>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<SMSMessage xmlns="http://xmlns.sony.net/d-cinema/sms/2007b">
<MessageHeader>
<Id>-1</Id>
<Type>PowerStatusList</Type>
<Timestamp>1770226327272</Timestamp>
<Source>LSM-100v2</Source>
</MessageHeader>
<MessageBody>
<PowerStatusList>
<PowerStatus>
<Device>SMS</Device>
<State>ON</State>
</PowerStatus>
<PowerStatus>
<Device>CSS</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>MARRIAGE</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>MB</Device>
<State>ON</State>
</PowerStatus>
<PowerStatus>
<Device>RAID</Device>
<State>ON</State>
</PowerStatus>
<PowerStatus>
<Device>PRJ</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>ENCLOSURE</Device>
<State>UNKNOWN</State>
</PowerStatus>
<PowerStatus>
<Device>UPS</Device>
<State>ON</State>
</PowerStatus>
</PowerStatusList>
</MessageBody>
</SMSMessage>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<SMSMessage xmlns="http://xmlns.sony.net/d-cinema/sms/2007b">
<MessageHeader>
<Id>-1</Id>
<Type>ShowStatus</Type>
<Timestamp>1770226334530</Timestamp>
<Source>LSM-100v2</Source>
</MessageHeader>
<MessageBody>
<ShowStatus>
<PlayState>INTERRUPTED</PlayState>
<ShowStatusDetail>
<Type>SPL</Type>
<Id>urn:uuid:20ba4558-150c-4c0d-bb9e-d04f843b1897</Id>
<RemainingTime>151098</RemainingTime>
<ElapsedTime>6706902</ElapsedTime>
<TotalDuration>6858000</TotalDuration>
<CurrentEventId>urn:uuid:84b1b984-d53b-40a1-9a3c-ea3e84ce25ed</CurrentEventId>
<CurrentEventType>CPL</CurrentEventType>
<IsStoppedByMalfunction>false</IsStoppedByMalfunction>
<RewindTimeList>30,60,120,180,300</RewindTimeList>
<MalfunctionTime>0</MalfunctionTime>
</ShowStatusDetail>
<PlayBackMode>SCHEDULED</PlayBackMode>
<AtmosPlayingStatus>NONE</AtmosPlayingStatus>
</ShowStatus>
</MessageBody>
</SMSMessage>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<SMSMessage xmlns="http://xmlns.sony.net/d-cinema/sms/2007b">
<MessageHeader>
<Id>-1</Id>
<Type>ErrorResponse</Type>
<Timestamp>1770199950331</Timestamp>
<Source>LSM-100v2</Source>
</MessageHeader>
<MessageBody>
<ErrorResponse>
<Severity>INFO</Severity>
<Code>100</Code>
<Message>Request+successfully+processed.</Message>
<Solution></Solution>
</ErrorResponse>
</MessageBody>
</SMSMessage>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<SMSMessage xmlns="http://xmlns.sony.net/d-cinema/sms/2007b">
<MessageHeader>
<Id>-1</Id>
<Type>MBStorageUsageList</Type>
<Timestamp>1770226321826</Timestamp>
<Source>LSM-100v2</Source>
</MessageHeader>
<MessageBody>
<MBStorageUsageList>
<MBStorageUsage>
<FileSystem>DCP</FileSystem>
<TotalCapacity>3760916510924</TotalCapacity>
<SpaceInUse>657203859456</SpaceInUse>
<FreeSpace>3103712651468</FreeSpace>
</MBStorageUsage>
</MBStorageUsageList>
</MessageBody>
</SMSMessage>

37
pyutils/utils.py Normal file
View File

@@ -0,0 +1,37 @@
import signal
from logging import Logger
from influxdb_client_3 import Point
class SignalHandler:
running: bool
logger: Logger
def __init__(self, logger):
self.running: bool = True
self.logger: Logger = logger
signal.signal(signal.SIGINT, self._handle_sigint)
signal.signal(signal.SIGTERM, self._handle_sigint)
def _handle_sigint(self, signum, frame):
self.logger.info(f"Received SIGNAL: {signal.strsignal(signum)}")
self.running = False
def dict2Point(measurement: str, fields: dict, tags: dict | None = None) -> Point:
p = Point(measurement)
for k,v in fields.items():
p.field(k,v)
if tags:
for k,v in tags.items():
p.tag(k,v)
return p
def convertInt(d: dict) -> dict:
for k,v in d.items():
if str.isdecimal(v):
d[k] = int(v)
return d
def convertIntList(l: list[dict]) -> list[dict]:
for n,d in enumerate(l):
l[n] = convertInt(d)
return l

View File

@@ -1,9 +1,12 @@
FROM python:3.12-alpine FROM python:3.12-alpine
ARG BUILD_VER
RUN apk update && apk upgrade --no-cache RUN apk update && apk upgrade --no-cache
RUN pip install --no-cache-dir RouterOS-API influxdb-client RUN pip install --no-cache-dir RouterOS-API influxdb3-python
COPY ./routermon.py /home/routermon.py COPY ./routermon.py /home/routermon.py
COPY ./utils.py /home/pyutils/utils.py
ENV VER=${BUILD_VER}
CMD [ "python", "/home/routermon.py" ] CMD [ "python", "/home/routermon.py" ]

View File

@@ -2,88 +2,81 @@ import os
import sys import sys
import time import time
import logging import logging
import signal
import json import json
import routeros_api import routeros_api
from influxdb_client.client.write.point import Point from pyutils.utils import *
from influxdb_client.client.influxdb_client import InfluxDBClient from influxdb_client_3 import InfluxDBClient3, Point
from influxdb_client.client.write_api import ASYNCHRONOUS, SYNCHRONOUS
# Get environment variables # Get environment variables
env = dict(os.environ) env = dict(os.environ)
LOGGER: logging.Logger LOGGER: logging.Logger
class SignalHandler: ##################
running: bool ###### MAIN ######
##################
def __init__(self): def main() -> int:
self.running: bool = True
signal.signal(signal.SIGINT, self._handle_sigint)
signal.signal(signal.SIGTERM, self._handle_sigint)
def _handle_sigint(self, signum, frame):
self.running = False
def main():
INTERVAL = int(env['INTERVAL']) INTERVAL = int(env['INTERVAL'])
# Init InfluxDB try:
write_client = InfluxDBClient(url=env['INFLUXDB_URL'], # Init InfluxDB-v3 Client
write_client = InfluxDBClient3(host=env['INFLUXDB_URL'],
token=env['INFLUXDB_TOKEN'], token=env['INFLUXDB_TOKEN'],
org=env['INFLUXDB_ORG']) database=env['INFLUXDB_DATABASE'])
write_api = write_client.write_api(write_options=ASYNCHRONOUS) # Init routerOS API
# Init routerOS API connection = routeros_api.RouterOsApiPool(env['MIKROTIK_IP'],
connection = routeros_api.RouterOsApiPool(env['MIKROTIK_IP'], username=env['MIKROTIK_USER'],
username=env['MIKROTIK_USER'], password=env['MIKROTIK_PASSWORD'],
password=env['MIKROTIK_PASSWORD'], plaintext_login=True)
plaintext_login=True) api = connection.get_api()
api = connection.get_api() except Exception as e:
LOGGER.error(e)
return 1
finally:
LOGGER.info(f"InfluxDB Connected: [{env['INFLUXDB_URL']}/{env['INFLUXDB_DATABASE']}]")
LOGGER.info(f"Mikrotik Connected: [{env['MIKROTIK_IP']}]")
run: SignalHandler = SignalHandler() ##############################
last = 0 ########## MAIN LOOP #########
if_points = [] ##############################
if_stats_old = api.get_resource('/interface/ethernet').call('print', {'proplist': 'name,rx-bytes,tx-bytes'}) last: float = 0
for n,d in enumerate(if_stats_old): handler: SignalHandler = SignalHandler(LOGGER)
for k,v in d.items(): if_stats_old = convertIntList(api.get_resource('/interface/ethernet').call('print', {'proplist': 'name,rx-bytes,tx-bytes'}))
if str.isdecimal(v): while handler.running:
if_stats_old[n][k] = int(v)
### MAIN LOOP ###
while run:
try: try:
now = time.time() now:float = time.time()
if_stats = api.get_resource('/interface/ethernet').call('print', {'proplist': 'name,rx-bytes,tx-bytes'}) if_points: list[Point] = []
hw_stats = api.get_resource('/system/resource').call('print', {'proplist':'uptime,cpu-load'})[0] if_stats: list[dict] = convertIntList(api.get_resource('/interface/ethernet').call('print', {'proplist': 'name,rx-bytes,tx-bytes'}))
# calcolo della velocita' interfaccia a ogni ciclo hw_stats: dict[str,str] = convertInt(api.get_resource('/system/resource').call('print', {'proplist':'uptime,cpu-load,total-memory,free-memory'})[0])
for n,d in enumerate(if_stats): hw_stats['temperature'] = convertInt(api.get_resource('/system/health').call('print')[1])['value']
for k,v in d.items(): # Calcolo della velocita' interfaccia a ogni ciclo
if str.isdecimal(v): for n, _ in enumerate(if_stats):
if_stats[n][k] = int(v) if_name = if_stats[n].pop('name')
if_stats[n]['rx-rate'] = int((if_stats[n]['rx-bytes']-if_stats_old[n]['rx-bytes'])/(now-last)) if_stats[n]['rx-rate'] = int((if_stats[n]['rx-bytes']-if_stats_old[n]['rx-bytes'])/(INTERVAL))
if_stats[n]['tx-rate'] = int((if_stats[n]['tx-bytes']-if_stats_old[n]['tx-bytes'])/(now-last)) if_stats[n]['tx-rate'] = int((if_stats[n]['tx-bytes']-if_stats_old[n]['tx-bytes'])/(INTERVAL))
if_points.append( if_points.append(
Point("interfaces") dict2Point('interfaces', if_stats[n], {'interface': if_name})
.tag("interface", d['name']) )
.field('rx-rate', if_stats[n]['rx-rate']) write_client.write(record=if_points)
.field('tx-rate', if_stats[n]['tx-rate'])
) # Risorse del router
rs1 = write_api.write(bucket=env['INFLUXDB_BUCKET'], org=env['INFLUXDB_ORG'], write_client.write(record=dict2Point('resources',hw_stats))
record=if_points)
rs2 = write_api.write(bucket=env['INFLUXDB_BUCKET'], org=env['INFLUXDB_ORG'], # Salvo ultimo punto per il giro successivo
record=Point('resources').field('cpu',int(hw_stats['cpu-load']))
)
LOGGER.debug(f"InfluxWrite: W1:{rs1}, W2:{rs2}")
if_stats_old = if_stats if_stats_old = if_stats
last = time.time()
LOGGER.debug(f"\nInterfaces: {json.dumps(if_stats, indent = 2)}") LOGGER.debug(f"\nInterfaces: {json.dumps(if_stats, indent = 2)}")
LOGGER.debug(f"\nResources: {json.dumps(hw_stats, indent = 2)}") LOGGER.debug(f"\nResources: {json.dumps(hw_stats, indent = 2)}")
time.sleep(INTERVAL) last: float = time.time()
cycle_time: float = last - now
LOGGER.debug(f"Cycle Time: {cycle_time:4.3f}")
time.sleep(INTERVAL-cycle_time)
except Exception as e: except Exception as e:
print(f"Unexpected exception: [{e}]") print(f"Unexpected exception: [{e}]")
return 1 return 1
### END MAIN LOOP ### ##############################
###### END MAIN LOOP #########
##############################
connection.disconnect() connection.disconnect()
write_client.close()
return 0 return 0
if __name__ == "__main__": if __name__ == "__main__":
@@ -111,6 +104,7 @@ if __name__ == "__main__":
LOGGER.addHandler(cl) LOGGER.addHandler(cl)
LOGGER.warning(f"Routermon started on: {time.asctime()}") LOGGER.warning(f"Routermon started on: {time.asctime()}")
LOGGER.info(f"Routermon BUILD: {env.get("VER", "Test")}")
while main(): while main():
LOGGER.error("Main thread exited unexpectedly") LOGGER.error("Main thread exited unexpectedly")

26
upsmon/dataexchange.txt Normal file
View File

@@ -0,0 +1,26 @@
VP req: QMD
UPS resp: (#######WPHVT2K0 ###2000 80 1/1 230 230 04 12.0
VP req: QRI
UPS resp: (230.0 008 048.0 50.0
VP req: QHE
UPS resp: (242 218
VP req: QRI
UPS resp: (230.0 008 048.0 50.0
VP req: QGS
UPS resp: (230.9 50.0 230.7 50.1 001.0 013 373.7 379.4 054.4 ---.- 027.3 100000000001
VP req: QMOD
UPS resp: (L
VP req: QWS
UPS resp: (0000000000000000000000000000000000000000000000000000000000000000
VP req: QBV
UPS resp: (054.5 04 04 096 568
VP req: QSK1
UPS resp: (NAK
VP req: QSK2
UPS resp: (NAK
VP req: QFLAG
UPS resp: (EpbrashczDovegfm
VP req: QBYV
UPS resp: (264 170
VP req: QBYF
UPS resp: (53.0 47.0

16
upsmon/sniffer.py Normal file
View File

@@ -0,0 +1,16 @@
import serial
ups_port = "/dev/ttyUSB1"
usb_fake = "/dev/ttyUSBf"
ups = serial.Serial(port=ups_port, baudrate=2400, parity="N", bytesize=8, stopbits=1)
vp = serial.Serial(port=usb_fake, baudrate=2400, parity="N", bytesize=8, stopbits=1)
while True:
vp_request = vp.read_until(b'\r')
print(f'VP req: {vp_request.decode('ascii').strip()}')
ups.write(vp_request)
ups.flush()
ups_response = ups.read_until(b'\r')
print(f'UPS resp: {ups_response.decode('ascii').strip()}')
vp.write(ups_response)

View File

@@ -1,121 +1,176 @@
import os import os
import sys import sys
import time import time
import string
import serial import serial
import logging import logging
import signal
import json
from influxdb_client.client.write.point import Point from copy import deepcopy
from influxdb_client.client.influxdb_client import InfluxDBClient from pyutils.utils import *
from influxdb_client.client.write_api import ASYNCHRONOUS, SYNCHRONOUS from dataclasses import dataclass
from influxdb_client_3 import InfluxDBClient3, WriteOptions
# Get environment variables # Get environment variables
env = dict(os.environ) env = dict(os.environ)
LOGGER: logging.Logger LOGGER: logging.Logger
class SignalHandler: class UPScommand:
running: bool
def __init__(self): def send(self, port:serial.Serial, cmd: str):
self.running: bool = True port.write((cmd+'\r').encode('ascii'))
signal.signal(signal.SIGINT, self._handle_sigint) port.flush()
signal.signal(signal.SIGTERM, self._handle_sigint)
def _handle_sigint(self, signum, frame): def receive(self, port:serial.Serial, cmd: str) -> str:
self.running = False resp = port.read_until(expected=b'\r').decode('ascii').rstrip()
LOGGER.debug(f"{cmd} : {resp}")
return resp
def send(port: serial.Serial, d: str): def request(self, port:serial.Serial, cmd: str) -> list[str]:
port.write((d+'\r').encode('ascii')) self.send(port, cmd)
port.flush() return self.receive(port, cmd).lstrip('(').rstrip().split()
def asDict(self):
return deepcopy(self.__dict__)
def receive(port: serial.Serial, d: str) -> str: @dataclass
r = port.read_until(b'\r').decode('ascii').rstrip() class UPSstatus(UPScommand):
LOGGER.debug(f"{d} : {r}") inV: float
return r inF: float
outV: float
outF: float
current: float
loadPct: int
battV: float
temp: float
onLine: bool
onBatt: bool
ecoMode: bool
def bruteforceCommands(port: serial.Serial): def __init__(self, port: serial.Serial):
# T and S cause unwanted shutdown self.update(port)
letters = string.ascii_uppercase.replace('T','').replace('S','') return
LOGGER.debug(f"Test commands: {letters}")
for c in letters:
send(port, c)
receive(port, c)
for n in range(10):
d = c+f"{n:1d}"
send(port, d)
receive(port, d)
for n in range(100):
d = c+f"{n:02d}"
send(port, d)
receive(port, d)
def main(): def update(self, port:serial.Serial):
data = self.request(port=port, cmd="QGS")
self.inV = float(data[0])
self.inF = float(data[1])
self.outV = float(data[2])
self.outF = float(data[3])
self.current = float(data[4])
self.loadPct = int(data[5])
self.battV = float(data[8])
self.temp = float(data[10])
self.onLine = True if data[11].startswith('1') else False
self.onBatt = True if data[11].endswith('0') else False
self.ecoMode = True if data[11][4] == '1' else False
@dataclass
class UPSbattery(UPScommand):
battV: float
battPct: int
timeLeft: float
def __init__(self, port: serial.Serial):
self.update(port)
return
def update(self, port: serial.Serial):
data = self.request(port=port, cmd="QBV")
self.battV = float(data[0])
self.battPct = int(data[3])
self.timeLeft = round(int(data[4]) / 60.0, 1)
##################
###### MAIN ######
##################
def main() -> int:
INTERVAL = int(env['INTERVAL']) INTERVAL = int(env['INTERVAL'])
LOGGER.debug(json.dumps(env, indent=2)) UPS_COMMAND = "Q1"
run: SignalHandler = SignalHandler() UPS_STATUS = "QGS" # (Vin Fin Vout Fout Aout Load% ?1 ?2 VbatInt VbatExt Temp Flags
port = serial.Serial(port=env['PORT'], baudrate=int(env['BAUD']), bytesize=8, parity='N', stopbits=1) UPS_BATTERY = "QBV" # (Vbat n1 n2 Charge% RunMins
write_client = InfluxDBClient(url=env['INFLUXDB_URL'], UPS_MODE = "QMOD" # (Mode [Echo, Line, Battery?]
token=env['INFLUXDB_TOKEN'],
org=env['INFLUXDB_ORG']) try:
write_api = write_client.write_api(write_options=ASYNCHRONOUS) # Init InfluxDB-v3 Client
write_client = InfluxDBClient3(host=env['INFLUXDB_URL'],
token=env['INFLUXDB_TOKEN'],
database=env['INFLUXDB_DATABASE'])
# Init Serial port
port = serial.Serial(port=env['PORT'], baudrate=int(env['BAUD']), bytesize=8, parity='N', stopbits=1)
port.flush()
# Init Dataclasses
run: SignalHandler = SignalHandler(LOGGER)
status = UPSstatus(port)
battery = UPSbattery(port)
except Exception as e:
LOGGER.error(e)
return 1
finally:
LOGGER.info(f"InfluxDB Connected: [{env['INFLUXDB_URL']}/{env['INFLUXDB_DATABASE']}]")
LOGGER.info(f"Serial Port Open: [{env['PORT']}]")
##############################
########## MAIN LOOP #########
##############################
while run.running: while run.running:
try: try:
send(port, "Q1") # Update data
data = receive(port, "Q1").lstrip('(').split() status.update(port)
if len(data) < 8: LOGGER.debug(f"{repr(status)}")
LOGGER.error(f"Incomplete data: {data}") battery.update(port)
continue LOGGER.debug(f"{repr(battery)}")
values = {
'inV': float(data[0]), # Debug status Information when running on batteries
'outV': float(data[2]), if status.onBatt:
'loadPercent': float(data[3]), LOGGER.info(f" Status:\n{repr(status)}")
'lineFreq': float(data[4]), LOGGER.info(f"Battery:\n{repr(battery)}")
'timeLeft': float(data[5]),
'onBatt': True if str(data[7]).startswith('1') else False, # Write datapoint to Influx merging measurements
'onLine': True if str(data[7]).endswith('1') else False, datapoint = status.asDict() | battery.asDict()
} write_client.write(record=dict2Point(measurement='ups',
LOGGER.debug(f"UPS Status: \n{json.dumps(values, indent=2)}") fields=datapoint
if values['onBatt']: ))
LOGGER.info(f"OnBattery\n{json.dumps(values,indent=2)}") LOGGER.debug(f"Influx Write: {datapoint}")
p = Point('ups') # Sleep and repeat
for k,v in values.items():
p.field(k,v)
write_api.write(bucket=env['INFLUXDB_BUCKET'], org=env['INFLUXDB_ORG'], record=p)
time.sleep(INTERVAL) time.sleep(INTERVAL)
except Exception as e: except Exception as e:
print(f"Unexpected exception: [{e}]") print(f"Unexpected exception: [{e}]")
return 1 return 1
##############################
###### END MAIN LOOP #########
##############################
port.close() port.close()
write_client.close()
LOGGER.warning("Main thread exited normally")
return 0
if __name__ == "__main__": if __name__ == "__main__":
# Logger Constants # Logger Constants
LOG_FORMAT = '%(asctime)s| %(levelname)-7s|%(funcName)-10s|%(lineno)-3d: %(message)-50s' LOG_FORMAT = '%(asctime)s| %(levelname)-7s|%(funcName)-10s|%(lineno)-3d: %(message)-50s'
# Enabling Logger # Enabling Logger
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.DEBUG) LOGGER.setLevel(logging.DEBUG)
LOGGER.propagate = False LOGGER.propagate = False
formatter = logging.Formatter(LOG_FORMAT, None) formatter = logging.Formatter(LOG_FORMAT, None)
levels = logging.getLevelNamesMapping() levels = logging.getLevelNamesMapping()
# File logging # File logging
log_name = os.path.abspath(env['LOG_FILE']) log_name = os.path.abspath(env['LOG_FILE'])
fh = logging.FileHandler(log_name) fh = logging.FileHandler(log_name)
fh.setLevel(levels[env['LOG_FILE_LVL']]) fh.setLevel(levels[env['LOG_FILE_LVL']])
fh.setFormatter(formatter) fh.setFormatter(formatter)
LOGGER.addHandler(fh) LOGGER.addHandler(fh)
# Console logging # Console logging
cl = logging.StreamHandler(sys.stdout) cl = logging.StreamHandler(sys.stdout)
cl.setLevel(levels[env['LOG_CLI_LVL']]) cl.setLevel(levels[env['LOG_CLI_LVL']])
cl.setFormatter(formatter) cl.setFormatter(formatter)
LOGGER.addHandler(cl) LOGGER.addHandler(cl)
LOGGER.warning(f"UPSmon started on: {time.asctime()}") LOGGER.warning(f"UPSmon started on: {time.asctime()}")
LOGGER.info(f"UPSmon BUILD: {env.get("VER", "Test")}")
while main(): while main():
LOGGER.error("Main thread exited unexpectedly") LOGGER.error("Main thread exited unexpectedly")
time.sleep(15) time.sleep(15)

View File

@@ -1,9 +1,12 @@
FROM python:3.12-alpine FROM python:3.12-alpine
ARG BUILD_VER
RUN apk update && apk upgrade --no-cache RUN apk update && apk upgrade --no-cache
RUN pip install --no-cache-dir pyserial RouterOS-API influxdb-client RUN pip install --no-cache-dir pyserial RouterOS-API influxdb3-python
COPY ./ups.py /home/ups.py COPY ./ups.py /home/ups.py
COPY ./utils.py /home/pyutils/utils.py
ENV VER=${BUILD_VER}
CMD [ "python", "/home/ups.py" ] CMD [ "python", "/home/ups.py" ]