Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
co2
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nikita Yurishev
co2
Commits
61a44a42
Commit
61a44a42
authored
Sep 04, 2024
by
Nikita Yurishev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
changed variables name and add service files
parent
fdbf4366
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
109 additions
and
76 deletions
+109
-76
influxConnection.cpython-39.pyc
__pycache__/influxConnection.cpython-39.pyc
+0
-0
influxWriter.cpython-39.pyc
__pycache__/influxWriter.cpython-39.pyc
+0
-0
co2.py
co2.py
+83
-76
co2.service
services/co2.service
+15
-0
co2.timer
services/co2.timer
+11
-0
No files found.
__pycache__/influxConnection.cpython-39.pyc
deleted
100644 → 0
View file @
fdbf4366
File deleted
__pycache__/influxWriter.cpython-39.pyc
deleted
100644 → 0
View file @
fdbf4366
File deleted
co2.py
View file @
61a44a42
...
...
@@ -8,148 +8,155 @@ import sys
import
socket
#from influxWriter import InfluxWriter
from
influxConnection
import
InfluxConnection
CO2_USB_MFG
=
'Holtek'
CO2_USB_PRD
=
'USB-zyTemp'
CO2_USB_MANUFACTURER
=
'Holtek'
CO2_USB_PRODUCT
=
'USB-zyTemp'
# Ignore first 5 measurements during self-calibration after power-up
IGNORE_N_MEASUREMENTS
=
5
IGNORE_
FIRST_
N_MEASUREMENTS
=
5
l
=
log
.
getLogger
(
'zytemp'
)
l
ogger
=
log
.
getLogger
(
'zytemp'
)
_
CO2MON_MAGIC_WORD
=
b
'Htemp99e'
_
CO2MON_MAGIC_TABLE
=
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
CO2MON_MAGIC_WORD
=
b
'Htemp99e'
CO2MON_MAGIC_TABLE
=
(
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
)
def
list_to_longint
(
x
):
return
sum
([
val
<<
(
i
*
8
)
for
i
,
val
in
enumerate
(
x
[::
-
1
])])
def
list_to_longint
(
byte_list
):
return
sum
([
val
<<
(
i
*
8
)
for
i
,
val
in
enumerate
(
byte_list
[::
-
1
])])
def
longint_to_list
(
x
):
return
[(
x
>>
i
)
&
0xFF
for
i
in
(
56
,
48
,
40
,
32
,
24
,
16
,
8
,
0
)]
def
longint_to_list
(
integer_value
):
return
[(
integer_value
>>
i
)
&
0xFF
for
i
in
(
56
,
48
,
40
,
32
,
24
,
16
,
8
,
0
)]
class
ZyTemp
():
MEASUREMENTS
=
{
0x50
:
{
'name'
:
'CO2'
,
'unit'
:
'ppm'
,
'conversion'
:
lambda
x
:
x
,
'conversion'
:
lambda
value
:
value
,
},
0x42
:
{
'name'
:
'Temperature'
,
'unit'
:
'°C'
,
'conversion'
:
lambda
x
:
(
x
*
0.0625
)
-
273.15
,
'conversion'
:
lambda
value
:
(
value
*
0.0625
)
-
273.15
,
},
}
def
__init__
(
self
,
hid
dev
,
decrypt
=
True
):
self
.
h
=
hiddev
self
.
measurements_to_ignore
=
IGNORE_N_MEASUREMENTS
self
.
values
=
{
v
[
'name'
]:
None
for
v
in
ZyTemp
.
MEASUREMENTS
.
values
()}
def
__init__
(
self
,
hid
_device
,
decrypt
=
True
):
self
.
h
id_device
=
hid_device
self
.
measurements_to_ignore
=
IGNORE_
FIRST_
N_MEASUREMENTS
self
.
sensor_
values
=
{
v
[
'name'
]:
None
for
v
in
ZyTemp
.
MEASUREMENTS
.
values
()}
self
.
_magic_word
=
[((
w
<<
4
)
&
0xFF
)
|
(
w
>>
4
)
for
w
in
bytearray
(
_
CO2MON_MAGIC_WORD
)]
self
.
_magic_table
=
_
CO2MON_MAGIC_TABLE
self
.
_magic_table_int
=
list_to_longint
(
_
CO2MON_MAGIC_TABLE
)
self
.
magic_word_bytes
=
[((
word
<<
4
)
&
0xFF
)
|
(
word
>>
4
)
for
word
in
bytearray
(
CO2MON_MAGIC_WORD
)]
self
.
magic_table
=
CO2MON_MAGIC_TABLE
self
.
magic_table_integer
=
list_to_longint
(
CO2MON_MAGIC_TABLE
)
#self.influx_writer = InfluxWriter()
self
.
influx_writer
=
InfluxConnection
()
# Создаем объект для работы с InfluxDB
self
.
influx_connection
=
InfluxConnection
()
# Создаем объект для работы с InfluxDB
if
decrypt
:
self
.
h
.
send_feature_report
(
self
.
_
magic_table
)
self
.
h
id_device
.
send_feature_report
(
self
.
magic_table
)
else
:
self
.
h
.
send_feature_report
(
b
'
\xc4\xc6\xc0\x92\x40\x23\xdc\x96
'
)
self
.
h
id_device
.
send_feature_report
(
b
'
\xc4\xc6\xc0\x92\x40\x23\xdc\x96
'
)
def
__del__
(
self
):
self
.
h
.
close
()
self
.
h
id_device
.
close
()
def
update
(
self
,
key
,
value
,
values
):
values
[
key
]
=
value
def
update
_sensor_value
(
self
,
measurement_key
,
measurement_value
,
sensor_
values
):
sensor_values
[
measurement_key
]
=
measurement_
value
if
all
(
value
is
not
None
for
value
in
values
.
values
()):
if
all
(
value
is
not
None
for
value
in
sensor_
values
.
values
()):
sensor_id
=
socket
.
gethostname
()
print
(
f
"{sensor_id}: {values}"
)
#Проверка записи в InfluxDB
print
(
f
"{sensor_id}: {
sensor_
values}"
)
#
Проверка записи в InfluxDB
try
:
self
.
influx_
writer
.
write_data
(
sensor_id
,
values
)
# Записываем данные в InfluxDB
self
.
influx_
connection
.
write_data
(
sensor_id
,
sensor_
values
)
# Записываем данные в InfluxDB
except
Exception
as
e
:
l
.
error
(
"failed to write data into InfluxDB: {e}
"
)
l
ogger
.
error
(
f
"Failed to write data into InfluxDB: {e}
"
)
sys
.
exit
(
0
)
#!
def
run_once
(
self
,
decrypt
=
False
):
while
True
:
try
:
r
=
self
.
h
.
read
(
8
,
timeout_ms
=
5000
)
r
eport_data
=
self
.
hid_device
.
read
(
8
,
timeout_ms
=
5000
)
except
OSError
as
err
:
l
.
error
(
f
'OS error: {err}'
)
l
ogger
.
error
(
f
'OS error: {err}'
)
return
if
not
r
:
l
.
error
(
f
'Read error or timeout'
)
self
.
h
.
close
()
if
not
r
eport_data
:
l
ogger
.
error
(
'Read error or timeout'
)
self
.
h
id_device
.
close
()
return
if
decrypt
:
m
sg
=
list_to_longint
([
r
[
i
]
for
i
in
[
2
,
4
,
0
,
7
,
1
,
6
,
5
,
3
]])
res
=
msg
^
self
.
_magic_table_int
res
=
(
res
>>
3
)
|
((
res
<<
61
)
&
0xFFFFFFFFFFFFFFFF
)
res
=
longint_to_list
(
res
)
r
=
[(
r
-
mw
)
&
0xFF
for
r
,
mw
in
zip
(
res
,
self
.
_magic_word
)]
if
len
(
r
)
<
5
or
r
[
4
]
!=
0x0d
:
l
.
debug
(
f
'Unexpected data from device: {r
}
\n
'
)
m
essage
=
list_to_longint
([
report_data
[
i
]
for
i
in
[
2
,
4
,
0
,
7
,
1
,
6
,
5
,
3
]])
res
ult
=
message
^
self
.
magic_table_integer
res
ult
=
(
result
>>
3
)
|
((
result
<<
61
)
&
0xFFFFFFFFFFFFFFFF
)
res
ult
=
longint_to_list
(
result
)
r
eport_data
=
[(
data
-
magic_word
)
&
0xFF
for
data
,
magic_word
in
zip
(
result
,
self
.
magic_word_bytes
)]
if
len
(
r
eport_data
)
<
5
or
report_data
[
4
]
!=
0x0d
:
l
ogger
.
debug
(
f
'Unexpected data from device: {report_data
}
\n
'
)
continue
if
r
[
3
]
!=
sum
(
r
[
0
:
3
])
&
0xff
:
if
r
eport_data
[
3
]
!=
sum
(
report_data
[
0
:
3
])
&
0xff
:
continue
m
_type
=
r
[
0
]
m
_val
=
r
[
1
]
<<
8
|
r
[
2
]
m
easurement_type
=
report_data
[
0
]
m
easurement_value
=
report_data
[
1
]
<<
8
|
report_data
[
2
]
try
:
m
=
ZyTemp
.
MEASUREMENTS
[
m
_type
]
m
easurement
=
ZyTemp
.
MEASUREMENTS
[
measurement
_type
]
except
KeyError
:
l
.
debug
(
f
'Unknown key {m
_type:02x}
\n
'
)
l
ogger
.
debug
(
f
'Unknown key {measurement
_type:02x}
\n
'
)
continue
m_name
,
m_unit
,
m_reading
=
m
[
'name'
],
m
[
'unit'
],
m
[
'conversion'
](
m_val
)
measurement_name
,
measurement_unit
,
measurement_converted_value
=
(
measurement
[
'name'
],
measurement
[
'unit'
],
measurement
[
'conversion'
](
measurement_value
)
)
ignore
=
self
.
measurements_to_ignore
>
0
ignore
_measurement
=
self
.
measurements_to_ignore
>
0
l
.
debug
(
f
'{m_name}: {m_reading:g} {m_unit}'
+
(
' (ignored)'
if
ignore
else
''
)
+
'
\n
'
)
logger
.
debug
(
f
'{measurement_name}: {measurement_converted_value:g} {measurement_unit}'
+
(
' (ignored)'
if
ignore_measurement
else
''
)
+
'
\n
'
)
if
not
ignore
:
self
.
update
(
m_name
,
m_reading
,
self
.
values
)
if
not
ignore
_measurement
:
self
.
update
_sensor_value
(
measurement_name
,
measurement_converted_value
,
self
.
sensor_
values
)
if
self
.
measurements_to_ignore
:
self
.
measurements_to_ignore
-=
1
def
get_hid
dev
():
def
get_hid
_device
():
hid_sensors
=
[
e
for
e
in
hid
.
enumerate
()
if
e
[
'manufacturer_string'
]
==
CO2_USB_MFG
and
e
[
'product_string'
]
==
CO2_USB_PRD
sensor
for
sensor
in
hid
.
enumerate
()
if
sensor
[
'manufacturer_string'
]
==
CO2_USB_MANUFACTURER
and
sensor
[
'product_string'
]
==
CO2_USB_PRODUCT
]
p
=
[]
for
s
in
hid_sensors
:
intf
,
path
,
vid
,
pid
=
(
s
[
k
]
for
k
in
(
'interface_number'
,
'path'
,
'vendor_id'
,
'product_id'
))
sensor_paths
=
[]
for
sensor
in
hid_sensors
:
interface_number
,
path
,
vendor_id
,
product_id
=
(
sensor
[
key
]
for
key
in
(
'interface_number'
,
'path'
,
'vendor_id'
,
'product_id'
))
path_str
=
path
.
decode
(
'utf-8'
)
l
.
info
(
f
'Found CO2 sensor at intf. {intf}, {path_str}, VID={vid:04x}, PID={pid:04x}'
)
p
.
append
(
path
)
if
not
p
:
l
.
error
(
'No device found'
)
logger
.
info
(
f
'Found CO2 sensor at interface {interface_number}, {path_str}, VID={vendor_id:04x}, PID={product_id:04x}'
)
sensor_paths
.
append
(
path
)
if
not
sensor_paths
:
logger
.
error
(
'No device found'
)
return
None
l
.
info
(
f
'Using device at {p
[0].decode("utf-8")}'
)
h
=
hid
.
device
()
h
.
open_path
(
p
[
0
])
return
h
l
ogger
.
info
(
f
'Using device at {sensor_paths
[0].decode("utf-8")}'
)
h
id_device
=
hid
.
device
()
h
id_device
.
open_path
(
sensor_paths
[
0
])
return
h
id_device
if
__name__
==
"__main__"
:
log
.
basicConfig
(
level
=
log
.
DEBUG
)
hid
dev
=
get_hiddev
()
if
hid
dev
is
None
:
hid
_device
=
get_hid_device
()
if
hid
_device
is
None
:
sys
.
exit
(
1
)
zytemp
=
ZyTemp
(
hiddev
)
zytemp
.
run_once
()
zytemp
_sensor
=
ZyTemp
(
hid_device
)
zytemp
_sensor
.
run_once
()
temperature
=
zytemp
.
values
.
get
(
'Temperature'
,
'N/A'
)
co2
=
zytemp
.
values
.
get
(
'CO2'
,
'N/A'
)
temperature
=
zytemp
_sensor
.
sensor_
values
.
get
(
'Temperature'
,
'N/A'
)
co2
_level
=
zytemp_sensor
.
sensor_
values
.
get
(
'CO2'
,
'N/A'
)
services/co2.service
0 → 100644
View file @
61a44a42
[Unit]
Description=co2 Service
After=network.target
[Service]
WorkingDirectory=/srv/nikyur/Projects/co2git/co2
ExecStart=/usr/bin/python3 /srv/nikyur/Projects/co2git/co2/co2.py
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
\ No newline at end of file
services/co2.timer
0 → 100644
View file @
61a44a42
[Unit]
Description=co2 Service every minute
[Timer]
OnCalendar=*:0/1
Unit=co2.service
[Install]
WantedBy=timers.target
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment