YACWC
This commit is contained in:
BIN
.track.py.swp
Normal file
BIN
.track.py.swp
Normal file
Binary file not shown.
2
__init__.py
Executable file
2
__init__.py
Executable file
@@ -0,0 +1,2 @@
|
||||
from .data_structures import CircularDict
|
||||
#from CommonCode import util
|
||||
BIN
__pycache__/__init__.cpython-310.pyc
Normal file
BIN
__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/__init__.cpython-311.pyc
Normal file
BIN
__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/__init__.cpython-312.pyc
Normal file
BIN
__pycache__/__init__.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/__init__.cpython-313.pyc
Normal file
BIN
__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/data_structures.cpython-310.pyc
Normal file
BIN
__pycache__/data_structures.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/data_structures.cpython-311.pyc
Normal file
BIN
__pycache__/data_structures.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/data_structures.cpython-312.pyc
Normal file
BIN
__pycache__/data_structures.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/data_structures.cpython-313.pyc
Normal file
BIN
__pycache__/data_structures.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/db_conn.cpython-310.pyc
Normal file
BIN
__pycache__/db_conn.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/db_conn.cpython-311.pyc
Normal file
BIN
__pycache__/db_conn.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/db_conn.cpython-312.pyc
Normal file
BIN
__pycache__/db_conn.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/db_conn.cpython-313.pyc
Normal file
BIN
__pycache__/db_conn.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/kwq.cpython-310.pyc
Normal file
BIN
__pycache__/kwq.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/kwq.cpython-312.pyc
Normal file
BIN
__pycache__/kwq.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/kwq.cpython-313.pyc
Normal file
BIN
__pycache__/kwq.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/naming.cpython-311.pyc
Normal file
BIN
__pycache__/naming.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/naming.cpython-312.pyc
Normal file
BIN
__pycache__/naming.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/settings.cpython-310.pyc
Normal file
BIN
__pycache__/settings.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/settings.cpython-312.pyc
Normal file
BIN
__pycache__/settings.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/settings.cpython-313.pyc
Normal file
BIN
__pycache__/settings.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/util.cpython-310.pyc
Normal file
BIN
__pycache__/util.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/util.cpython-311.pyc
Normal file
BIN
__pycache__/util.cpython-311.pyc
Normal file
Binary file not shown.
BIN
__pycache__/util.cpython-312.pyc
Normal file
BIN
__pycache__/util.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/util.cpython-313.pyc
Normal file
BIN
__pycache__/util.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/video_meta.cpython-312.pyc
Normal file
BIN
__pycache__/video_meta.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/video_meta.cpython-313.pyc
Normal file
BIN
__pycache__/video_meta.cpython-313.pyc
Normal file
Binary file not shown.
BIN
__pycache__/wq.cpython-310.pyc
Normal file
BIN
__pycache__/wq.cpython-310.pyc
Normal file
Binary file not shown.
BIN
__pycache__/wq.cpython-312.pyc
Normal file
BIN
__pycache__/wq.cpython-312.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
__pycache__/wq.cpython-313.pyc
Normal file
BIN
__pycache__/wq.cpython-313.pyc
Normal file
Binary file not shown.
15
baseObjects.py
Executable file
15
baseObjects.py
Executable file
@@ -0,0 +1,15 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
class BaseSensorPost(object):
|
||||
def __init__(self, sq, sensor_type):
|
||||
self.last_values = [None,None]
|
||||
self.last_measurement = None
|
||||
self.last_insert = datetime.now()
|
||||
self.sq = sq
|
||||
self.heartbeat_interval = 15*60
|
||||
self.sensor = sensor_type
|
||||
|
||||
def insert_heartbeat(self, time_init, sensor):
|
||||
ins = self.sq['t']['heartbeats'].insert().values(
|
||||
when = time_init, what = sensor)
|
||||
self.sq['s'].execute(ins)
|
||||
13
data_structures.py
Normal file
13
data_structures.py
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
from collections import UserDict, deque
|
||||
class CircularDict(UserDict):
|
||||
def __init__(self,init_data = None, max_len = 50):
|
||||
self.data = init_data if init_data is not None else dict()
|
||||
self.fkkeys = deque(self.data.keys(), max_len)
|
||||
self.max_len = max_len
|
||||
def __setitem__(self, k,v):
|
||||
self.fkkeys.append(k)
|
||||
self.data[k] = v
|
||||
to_rem = self.data.keys() - set(self.fkkeys)
|
||||
[self.data.pop(k) for k in to_rem]
|
||||
|
||||
356
db_conn.py
Executable file
356
db_conn.py
Executable file
@@ -0,0 +1,356 @@
|
||||
|
||||
|
||||
#tables_meta = ['motionlogs', 'floor2temperature', 'horizontalwheel', 'verticalwheel','heartbeats', 'activities','food_weight','weight','daily_counts','hourly_temperature','food_dispenser', 'food_forager', 'touch_surface_grid']
|
||||
import inspect
|
||||
import clickhouse_driver as ch
|
||||
from functools import partial
|
||||
import json
|
||||
|
||||
|
||||
|
||||
# %%
|
||||
|
||||
c_to_ch_dtype_map = {'uint8': 'UInt8', 'uint16':'UInt16', 'float32': 'Float32','datetime':'DateTime', 'point':'Point','str':'String', 'float':'Float32','int':'Int16'}
|
||||
class db_api():
|
||||
def __init__(self):
|
||||
host = '192.168.1.242'
|
||||
host = update_host(do_loopback, host)
|
||||
self.conn = ch.connect('clickhouse://'+host);
|
||||
self.client = ch.Client(host=host)
|
||||
self.cursor = self.conn.cursor()
|
||||
kff = ['altitude','humidity','pressure','temperature','weight','hydroponics_ph','hydroponics_ec','hydroponics_rtd']
|
||||
|
||||
for kv in kff:
|
||||
func_name = 'insert_'+kv
|
||||
func_set = partial(self.generic_when_where, first_key = kv)
|
||||
setattr(self, func_name, func_set)
|
||||
|
||||
|
||||
def get_query_time_filtered(self, table, time_start, time_end):
|
||||
cquery = f"select * from {table} where when > '{str(time_start)}' and when < '{str(time_end)}' order by when asc"
|
||||
return cquery
|
||||
|
||||
|
||||
def expand_to_list(self, vals): #dict of lists -> list of dicts
|
||||
max_len = 1
|
||||
for k,v in vals.items():
|
||||
if isinstance(v,list):
|
||||
max_len = max(max_len, len(v))
|
||||
|
||||
output = list()
|
||||
for i in range(max_len):
|
||||
output.append(dict())
|
||||
|
||||
for k,v in vals.items():
|
||||
if isinstance(v, list):
|
||||
for idx, val in enumerate(v):
|
||||
output[idx][k] = val
|
||||
else:
|
||||
for f in output:
|
||||
f[k] = v
|
||||
|
||||
return output
|
||||
|
||||
def get_insert_statement(self,table_name, keys):
|
||||
kvars = ', '.join(keys)
|
||||
return f'INSERT INTO {table_name} ({kvars}) values '
|
||||
|
||||
def insert(self, dd, table, schema = None):
|
||||
if schema is not None:
|
||||
table = schema + '.' + table
|
||||
|
||||
if isinstance(dd, dict):
|
||||
insert_this = self.expand_to_list( dd)
|
||||
else:
|
||||
insert_this = dd
|
||||
|
||||
keys = insert_this[0].keys()
|
||||
insert_statement = self.get_insert_statement(table,keys)
|
||||
|
||||
self.cursor.executemany(insert_statement, insert_this)
|
||||
|
||||
|
||||
def query(self, query, no_results = False, **kwargs):
|
||||
self.cursor.execute(query, **kwargs)
|
||||
if no_results:
|
||||
return None
|
||||
else:
|
||||
return self.cursor.fetchall()
|
||||
def generic_when_where(self, v_in , when = None, where = None, first_key = None):
|
||||
keys = [first_key,'where','when']
|
||||
table = 'nuggets.'+first_key
|
||||
cb = locals()
|
||||
cb[first_key] = v_in
|
||||
dd = {x:cb[x] for x in keys}
|
||||
|
||||
self.insert(dd, table)
|
||||
|
||||
|
||||
def get_table_create_statement(self, schema, table_name, dtypes, insert_when = False, nullable = set()):
|
||||
|
||||
entries = list()
|
||||
if insert_when:
|
||||
entries.append('`when` DateTime64(3)')
|
||||
|
||||
for field_name, data_type in dtypes.items():
|
||||
ch_dtype = c_to_ch_dtype_map[data_type]
|
||||
if field_name in nullable:
|
||||
ch_dtype = 'Nullable('+ch_dtype+')'
|
||||
entries.append( f' `{field_name}` {ch_dtype}')
|
||||
|
||||
|
||||
dtype_text = ',\n'.join(entries)
|
||||
|
||||
create_header = f'create table {schema}.{table_name} '
|
||||
|
||||
|
||||
create_footer = f' \nENGINE = ReplacingMergeTree\nORDER BY when\nSETTINGS index_granularity = 8192'
|
||||
create_statement = create_header + '\n(\n' + dtype_text + '\n)\n' + create_footer
|
||||
|
||||
return create_statement
|
||||
|
||||
def check_if_table_exists(self, schema, table_name):
|
||||
query = f'''SELECT count(*) as num_tables
|
||||
FROM information_schema.tables where table_schema == '{schema}' and table_name == '{table_name}' '''
|
||||
|
||||
return self.query(query)[0][0]== 1
|
||||
|
||||
|
||||
def get_table_contents(self, table, make_map = False, make_inv_map = False):
|
||||
query = f'select * from {table}'
|
||||
self.cursor.execute(query);
|
||||
results = self.cursor.fetchall()
|
||||
|
||||
if make_map:
|
||||
cm = dict()
|
||||
|
||||
for f in results:
|
||||
cm[f[0]] = f[1]
|
||||
return cm
|
||||
|
||||
if make_inv_map:
|
||||
cm = dict()
|
||||
for f in results:
|
||||
cm[f[1]] = f[0]
|
||||
return cm
|
||||
|
||||
|
||||
return results
|
||||
|
||||
|
||||
|
||||
# def insert_temperature(self, temperature, when = None, where = None):
|
||||
# keys = ['temperature','who','when']
|
||||
# table = 'nuggets.temperature'
|
||||
# cb = locals()
|
||||
# dd = {x:cb[x] for x in keys}
|
||||
# self.insert(dd, table, keys)
|
||||
|
||||
|
||||
# def insert_pressure(self, pressure, when = None, where = None):
|
||||
# keys = ['temperature','who','when']
|
||||
# table = 'nuggets.pressure'
|
||||
# cb = locals()
|
||||
# dd = {x:cb[x] for x in keys}
|
||||
# self.insert(dd, table, keys)
|
||||
|
||||
# def insert_weight(self, weight, when=None, where=None):
|
||||
# keys = ['weight','who','when']
|
||||
# table = 'nuggets.weight'
|
||||
# cb = locals()
|
||||
# dd = {x:cb[x] for x in keys}
|
||||
# self.insert(dd, table, keys)
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from sqlalchemy.engine import create_engine
|
||||
from sqlalchemy.schema import MetaData
|
||||
from sqlalchemy.orm import Session
|
||||
import os
|
||||
import json
|
||||
import socket
|
||||
if socket.gethostname() == 'tree':
|
||||
do_loopback = True
|
||||
else:
|
||||
do_loopback = False
|
||||
|
||||
def update_host(do_loopback, ip_addr):
|
||||
if do_loopback and ip_addr=='192.168.1.242':
|
||||
# print('Updating host to be 127.0.0.1')
|
||||
return '127.0.0.1'
|
||||
else:
|
||||
return ip_addr
|
||||
|
||||
def connect( user='postgres', password='', db='nuggets', host='192.168.1.242', port=5432, echo = False):
|
||||
|
||||
host = update_host(do_loopback, host)
|
||||
|
||||
|
||||
from sqlalchemy.engine import create_engine
|
||||
from sqlalchemy.schema import MetaData
|
||||
from sqlalchemy.orm import Session
|
||||
import os
|
||||
import json
|
||||
|
||||
if False:
|
||||
|
||||
user='postgres'
|
||||
password=''
|
||||
db='nuggets'
|
||||
host='192.168.1.242'
|
||||
port=5432
|
||||
echo = False
|
||||
|
||||
url = 'postgresql://{}:{}@{}:{}/{}'
|
||||
url = url.format(user, password, host, port, db)
|
||||
|
||||
conn = create_engine(url, connect_args={"application_name":"python_commoncode"}, echo = echo, future=True)
|
||||
if db == 'nuggets':
|
||||
schemas =['public','health','videos']
|
||||
elif db == 'winslow':
|
||||
schemas=['body','notes','sensors','video']
|
||||
|
||||
|
||||
|
||||
metadata = MetaData()
|
||||
for schema in schemas:
|
||||
metadata.reflect(conn, schema,views=True)
|
||||
|
||||
|
||||
session = Session(conn)
|
||||
|
||||
tables = {k.split('.')[-1]:v for k,v in metadata.tables.items()}
|
||||
|
||||
from sqlalchemy import text
|
||||
|
||||
def execute_sub(query_in, has_data = None):
|
||||
|
||||
if has_data is not None:
|
||||
with conn.connect() as cox:
|
||||
result = cox.execute(query_in, has_data)
|
||||
try:
|
||||
cox.commit()
|
||||
except:
|
||||
pass
|
||||
|
||||
if hasattr(query_in, 'compile'):
|
||||
|
||||
|
||||
compiled = query_in.compile(dialect=postgresql.dialect())
|
||||
|
||||
with conn.connect() as cox:
|
||||
result = cox.execute(query_in, compiled.params)
|
||||
try:
|
||||
cox.commit()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
else:
|
||||
with conn.connect() as cox:
|
||||
result = cox.execute(text(query_in))
|
||||
try:
|
||||
cox.commit()
|
||||
except:
|
||||
pass
|
||||
|
||||
return result
|
||||
|
||||
setattr(conn, 'execute',execute_sub)
|
||||
|
||||
|
||||
# with conn.connect() as ce:
|
||||
if True:
|
||||
ce = conn
|
||||
pid = ce.execute('select pg_backend_pid()').fetchall()[0][0]
|
||||
if not os.path.exists('/dev/shm/pg/'):
|
||||
try:
|
||||
os.mkdir('/dev/shm/pg')
|
||||
except:
|
||||
pass
|
||||
# os.chmod('/dev/shm/pg',0o777)
|
||||
|
||||
# fname = '/dev/shm/pg/'+str(pid)
|
||||
|
||||
details = list()
|
||||
for x in inspect.stack():
|
||||
details.append({'filename':x.filename,'function':x.function,'lineno':x.lineno})
|
||||
|
||||
# with open(fname,'w') as ff:
|
||||
# json.dump(details, ff, indent=4, sort_keys = False)
|
||||
# os.chmod(fname,0o777)
|
||||
# %%
|
||||
|
||||
return {'s':session, 't':tables, 'c':conn, 'm':metadata}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def old_connect( user='postgres', password='', db='nuggets', host='192.168.1.242', port=5432):
|
||||
|
||||
if False:
|
||||
user = 'postgres'
|
||||
password=''
|
||||
db='winslow'
|
||||
host='192.168.1.242'
|
||||
port=5432
|
||||
import time
|
||||
|
||||
|
||||
|
||||
from sqlalchemy import and_, func, Table, MetaData, create_engine, inspect
|
||||
from sqlalchemy.orm import Session, load_only
|
||||
from sqlalchemy.ext.automap import automap_base
|
||||
from sqlalchemy.pool import NullPool
|
||||
|
||||
url = 'postgresql://{}:{}@{}:{}/{}'
|
||||
url = url.format(user, password, host, port, db)
|
||||
|
||||
|
||||
conn = create_engine(url, client_encoding='utf8',poolclass=NullPool, future=True)
|
||||
|
||||
|
||||
def get_tables_in_schema(schema_name):
|
||||
|
||||
|
||||
output = conn.execute("SELECT table_name FROM information_schema.tables WHERE table_schema='"+schema_name+"'").fetchall()
|
||||
return [x[0] for x in output]
|
||||
|
||||
|
||||
schemas = [x.strip() for x in conn.execute('show search_path').fetchall()[0][0].split(',')]
|
||||
|
||||
|
||||
tables_meta = list()
|
||||
for schema in schemas:
|
||||
tables_meta.extend(get_tables_in_schema(schema))
|
||||
|
||||
|
||||
materialized_tables = [x[0] for x in conn.execute('select matviewname from pg_matviews')]
|
||||
tables_meta.extend(materialized_tables)
|
||||
|
||||
meta = MetaData(bind=conn)#, reflect = True)
|
||||
meta.reflect(conn)
|
||||
|
||||
|
||||
base = automap_base()
|
||||
base.prepare(conn, reflect=True)
|
||||
|
||||
session = Session(conn)
|
||||
tables = dict()
|
||||
|
||||
|
||||
|
||||
for table in tables_meta:
|
||||
try:
|
||||
tables[table] = Table(table, meta, #MetaData(),
|
||||
autoload=False, autoload_with=conn)
|
||||
except:
|
||||
print(table, 'broke')
|
||||
pass
|
||||
|
||||
|
||||
|
||||
return {'s':session, 't':tables, 'c':conn, 'm':meta, 'b':base}
|
||||
|
||||
|
||||
|
||||
103
distanceTracker.py
Executable file
103
distanceTracker.py
Executable file
@@ -0,0 +1,103 @@
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
import math
|
||||
import traceback
|
||||
from subprocess import check_output, call
|
||||
import syslog
|
||||
from db_conn import connect
|
||||
import dateutil.parser
|
||||
from datetime import timedelta, datetime
|
||||
sys.path.append('/home/thebears/Nextcloud/Designs/NuggetTracker/CommonCode/')
|
||||
from track import Temperature, VerticalWheel, ActivityLogger, Weight, BaseSensorPost, HorizontalWheel
|
||||
import os
|
||||
from sqlalchemy import func
|
||||
import syslog
|
||||
import redis
|
||||
|
||||
|
||||
|
||||
|
||||
do_break = False
|
||||
while True:
|
||||
try:
|
||||
sq = connect()
|
||||
do_break = True;
|
||||
except:
|
||||
syslog.syslog("Failed to connect, waiting 1 second and trying again")
|
||||
time.sleep(1)
|
||||
|
||||
if do_break:
|
||||
break
|
||||
|
||||
|
||||
curr_time = datetime.now()
|
||||
last_date = datetime(curr_time.year, curr_time.month, curr_time.day, 18, 0, 0)
|
||||
|
||||
if last_date > curr_time:
|
||||
curr_time = datetime.now() - timedelta(days=1)
|
||||
last_date = datetime(curr_time.year, curr_time.month, curr_time.day, 18, 0, 0)
|
||||
|
||||
r = redis.StrictRedis(host='192.168.1.242', port=6379, db=1)
|
||||
|
||||
|
||||
os.makedirs('/dev/shm/winslow/', exist_ok=True)
|
||||
|
||||
call(['chmod','777','/dev/shm/winslow/'])
|
||||
|
||||
|
||||
res = sq['s'].query(func.count(sq['t']['horizontalwheel'].c.transittime)).filter(sq['t']['horizontalwheel'].c.timestamp > last_date).all()
|
||||
total_counts = res[0][0]
|
||||
|
||||
r.set('nugget_run_counts', total_counts)
|
||||
|
||||
|
||||
|
||||
|
||||
#1500 turns is 1/4 mile
|
||||
|
||||
threshold_for_next_mealie = 1500
|
||||
flipped_stuff = list()
|
||||
|
||||
bins_per_day = 18
|
||||
|
||||
|
||||
last_iter = min([int(math.floor(total_counts / threshold_for_next_mealie)),bins_per_day])
|
||||
|
||||
while True:
|
||||
do_rotate = False
|
||||
next_date = last_date + timedelta(days = 1)
|
||||
|
||||
if datetime.now() > next_date:
|
||||
if next_date not in flipped_stuff:
|
||||
do_rotate = True
|
||||
|
||||
if do_rotate is True:
|
||||
curr_time = datetime.now()
|
||||
last_date = datetime(curr_time.year, curr_time.month, curr_time.day, 18, 0, 0)
|
||||
flipped_stuff.append(last_date)
|
||||
syslog.syslog('Resetting time to '+str(last_date))
|
||||
last_iter = 0
|
||||
r.set('nugget_run_counts', 0)
|
||||
|
||||
|
||||
|
||||
|
||||
# res = sq['s'].query(func.count(sq['t']['horizontalwheel'].c.transittime)).filter(sq['t']['horizontalwheel'].c.timestamp > last_date).all()
|
||||
# total_counts = res[0][0]
|
||||
|
||||
total_counts = int(r.get('nugget_run_counts'))
|
||||
curr_iter = min([int(math.floor(total_counts / threshold_for_next_mealie)),bins_per_day])
|
||||
syslog.syslog('Total: '+str(total_counts)+' Current bin: '+str(curr_iter)+ ' Redis Count:' + str(total_counts))
|
||||
|
||||
if curr_iter != last_iter:
|
||||
last_iter = curr_iter
|
||||
open('/dev/shm/winslow/mealies2_open.txt','w').close()
|
||||
call(['chmod','777','/dev/shm/winslow'])
|
||||
syslog.syslog("OPENING MEALIES")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
time.sleep(5)
|
||||
73
frozen
Normal file
73
frozen
Normal file
@@ -0,0 +1,73 @@
|
||||
annotated-types==0.7.0
|
||||
anyio==4.10.0
|
||||
asttokens==3.0.0
|
||||
bounded-pool-executor==0.0.3
|
||||
certifi==2025.8.3
|
||||
charset-normalizer==3.4.3
|
||||
click==8.2.1
|
||||
colored==2.3.1
|
||||
decorator==5.2.1
|
||||
dnspython==2.7.0
|
||||
email-validator==2.3.0
|
||||
executing==2.2.1
|
||||
fastapi==0.116.1
|
||||
fastapi-cli==0.0.10
|
||||
fastapi-cloud-cli==0.1.5
|
||||
fastapi-server-session==0.0.1
|
||||
h11==0.16.0
|
||||
httpcore==1.0.9
|
||||
httptools==0.6.4
|
||||
httpx==0.28.1
|
||||
idna==3.10
|
||||
ipython==9.5.0
|
||||
ipython_pygments_lexers==1.1.1
|
||||
jedi==0.19.2
|
||||
Jinja2==3.1.6
|
||||
kafka-python==2.2.15
|
||||
lttb==0.3.2
|
||||
lxml==6.0.1
|
||||
markdown-it-py==4.0.0
|
||||
MarkupSafe==3.0.2
|
||||
matplotlib-inline==0.1.7
|
||||
mdurl==0.1.2
|
||||
## !! Could not determine repository location
|
||||
-e /home/thebears/Seafile/Designs/Code/Python
|
||||
numpy==1.26.4
|
||||
parso==0.8.5
|
||||
pexpect==4.9.0
|
||||
pqdm==0.2.0
|
||||
prompt_toolkit==3.0.52
|
||||
psutil==7.0.0
|
||||
ptyprocess==0.7.0
|
||||
pure_eval==0.2.3
|
||||
pydantic==2.11.7
|
||||
pydantic_core==2.33.2
|
||||
Pygments==2.19.2
|
||||
pystemd==0.13.4
|
||||
python-dotenv==1.1.1
|
||||
python-multipart==0.0.20
|
||||
python-systemd==0.0.9
|
||||
PyYAML==6.0.2
|
||||
redis==6.4.0
|
||||
redis-cli==1.0.1
|
||||
requests==2.32.5
|
||||
rich==14.1.0
|
||||
rich-toolkit==0.15.0
|
||||
rignore==0.6.4
|
||||
sentry-sdk==2.35.2
|
||||
shellingham==1.5.4
|
||||
sniffio==1.3.1
|
||||
stack-data==0.6.3
|
||||
starlette==0.47.3
|
||||
systemd-python @ git+https://github.com/systemd/python-systemd.git@903142423452c4dd18110b7f8a953dabb2031e49
|
||||
tqdm==4.67.1
|
||||
traitlets==5.14.3
|
||||
typer==0.17.3
|
||||
typing-inspection==0.4.1
|
||||
typing_extensions==4.15.0
|
||||
urllib3==2.5.0
|
||||
uvicorn==0.35.0
|
||||
uvloop==0.21.0
|
||||
watchfiles==1.1.0
|
||||
wcwidth==0.2.13
|
||||
websockets==15.0.1
|
||||
15
get_amts.py
Executable file
15
get_amts.py
Executable file
@@ -0,0 +1,15 @@
|
||||
from db_conn import connect
|
||||
from sqlalchemy import func
|
||||
sys.path.append('/home/thebears/Nextcloud/Designs/NuggetTracker/CommonCode/')
|
||||
|
||||
sq = connect()
|
||||
|
||||
curr_time = datetime.now()
|
||||
last_date = datetime(curr_time.year, curr_time.month, curr_time.day, 18, 0, 0)
|
||||
|
||||
|
||||
last_beat = {i:last_date for i in range(4)}
|
||||
threshold_for_next_mealie = 25
|
||||
min_time = 10;
|
||||
|
||||
res = sq['s'].query(func.count(sq['t']['horizontalwheel'].c.transittime)).filter(sq['t']['horizontalwheel'].c.timestamp > last_date).all()
|
||||
54
kwq.py
Normal file
54
kwq.py
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env python
|
||||
from enum import Enum
|
||||
import json
|
||||
import sys
|
||||
from kafka import KafkaProducer, KafkaConsumer
|
||||
|
||||
|
||||
bootstrap_server = ["192.168.1.242:19092"]
|
||||
|
||||
|
||||
class TOPICS():
|
||||
videos_to_score_detection = "videos_to_score_detection"
|
||||
videos_scored_detection="videos_scored_detection"
|
||||
videos_with_nuggets="videos_with_nuggets"
|
||||
videos_no_json="videos_no_json"
|
||||
videos_without_nuggets="videos_without_nuggets"
|
||||
videos_embedding_in_db="videos_embed_in_db"
|
||||
videos_embedding_in_db_fail = "videos_embed_in_db_fail"
|
||||
|
||||
|
||||
serializer = lambda v: json.dumps(v).encode("utf-8")
|
||||
deserializer = json.loads
|
||||
|
||||
producer = KafkaProducer(
|
||||
bootstrap_servers=bootstrap_server,
|
||||
key_serializer=serializer,
|
||||
value_serializer=serializer,
|
||||
request_timeout_ms=15000, # 15s (keep small)
|
||||
max_block_ms=10000, # 10s max blocking
|
||||
metadata_max_age_ms=300000,
|
||||
retry_backoff_ms=100,
|
||||
linger_ms=5,
|
||||
retries=3,
|
||||
security_protocol='SASL_PLAINTEXT', # change to SASL_SSL if TLS is enabled
|
||||
sasl_mechanism='SCRAM-SHA-256',
|
||||
sasl_plain_username='superuser',
|
||||
sasl_plain_password='marybear'
|
||||
)
|
||||
|
||||
|
||||
def create_consumer(group_id = None, client_id = None):
|
||||
return KafkaConsumer(
|
||||
bootstrap_servers=bootstrap_server,
|
||||
key_deserializer=deserializer,
|
||||
value_deserializer=deserializer,
|
||||
enable_auto_commit = False,
|
||||
group_id=group_id,
|
||||
client_id = client_id,
|
||||
auto_offset_reset = 'earliest',
|
||||
security_protocol='SASL_PLAINTEXT', # change to SASL_SSL if TLS is enabled
|
||||
sasl_mechanism='SCRAM-SHA-256',
|
||||
sasl_plain_username='superuser',
|
||||
sasl_plain_password='marybear'
|
||||
)
|
||||
6
kwq_test.py
Normal file
6
kwq_test.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from CommonCode import kwq
|
||||
topic = 'whatsup'
|
||||
kwq.producer.send("hello",'world')
|
||||
for x in range(100):
|
||||
kwq.producer.send(topic, 'num_'+str(x))
|
||||
|
||||
54
naming.py
Executable file
54
naming.py
Executable file
@@ -0,0 +1,54 @@
|
||||
|
||||
|
||||
|
||||
class str_with_attr(str):
|
||||
def __new__(cls, val):
|
||||
obj = str.__new__(cls, val)
|
||||
return obj
|
||||
|
||||
|
||||
def get_floor_redis_keys(floor_num):
|
||||
keys = dict()
|
||||
|
||||
swa = str_with_attr
|
||||
|
||||
keys['vis_status'] = swa( 'nugget_house_lighting_'+str(floor_num)+'_vis_status' )
|
||||
keys['vis_status'].default = 'off'
|
||||
keys['vis_status'].dtype = str
|
||||
|
||||
keys['ir_status'] = swa( 'nugget_house_lighting_'+str(floor_num)+'_ir_status' )
|
||||
keys['ir_status'].default = 'on'
|
||||
keys['ir_status'].dtype = str
|
||||
|
||||
keys['vis_intensity'] = swa( 'nugget_house_lighting_'+str(floor_num)+'_vis_intensity' )
|
||||
keys['vis_intensity'].default = 0
|
||||
keys['vis_intensity'].dtype = int
|
||||
|
||||
keys['ir_intensity'] = swa( 'nugget_house_lighting_'+str(floor_num)+'_ir_intensity')
|
||||
keys['ir_intensity'].default = 100
|
||||
keys['ir_intensity'].dtype = int
|
||||
|
||||
|
||||
keys['has_changed'] = swa('nugget_house_lighting_'+str(floor_num)+'_has_changed')
|
||||
keys['has_changed'].default = True
|
||||
keys['has_changed'].dtype = bool
|
||||
|
||||
return keys
|
||||
|
||||
|
||||
|
||||
def get_redis_values(r, keys):
|
||||
out = dict()
|
||||
for k,v in keys.items():
|
||||
redis_val = r.get(v)
|
||||
if redis_val is None:
|
||||
redis_val = 'None'
|
||||
else:
|
||||
redis_val = v.dtype(redis_val.decode('UTF-8'))
|
||||
|
||||
out[k] = redis_val
|
||||
|
||||
return out
|
||||
|
||||
|
||||
|
||||
54
settings.py
Normal file
54
settings.py
Normal file
@@ -0,0 +1,54 @@
|
||||
import logging
|
||||
import sys, os
|
||||
from systemd.journal import JournalHandler
|
||||
from colored import stylize, fore, Style, back
|
||||
from functools import partial
|
||||
from colored import set_tty_aware
|
||||
|
||||
|
||||
log_format = '%(asctime)s|%(levelname)s|%(filename)s⮞%(funcName)s⮞%(lineno)d|%(message)s'
|
||||
|
||||
|
||||
def get_logger(_name, file_path = None, stdout=False, systemd=False, level = logging.DEBUG):
|
||||
logger = logging.getLogger()
|
||||
logger.handlers.clear()
|
||||
env_level = os.getenv("LOGLEVEL")
|
||||
if env_level is not None:
|
||||
level = env_level
|
||||
|
||||
if level is not None:
|
||||
logger.setLevel(level)
|
||||
|
||||
formatter = logging.Formatter(log_format)
|
||||
if file_path is not None:
|
||||
file_handler = logging.FileHandler(file_path, mode='a')
|
||||
file_handler.setFormatter(formatter)
|
||||
file_handler.setLevel(logging.DEBUG)
|
||||
logger.addHandler(file_handler)
|
||||
|
||||
if stdout:
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setFormatter(formatter)
|
||||
stdout_handler.setLevel(logging.INFO)
|
||||
logger.addHandler(stdout_handler)
|
||||
|
||||
if systemd:
|
||||
systemd_handler = JournalHandler()
|
||||
systemd_handler.setFormatter(formatter)
|
||||
logger.addHandler(systemd_handler)
|
||||
|
||||
return logger
|
||||
|
||||
|
||||
|
||||
def stylize_interface(text, fore_256=None, back_256=None, style=None):
|
||||
return fore(fore_256)+back(back_256)+style+text+Style.reset
|
||||
|
||||
set_tty_aware(False)
|
||||
|
||||
class LogColorize(object):
|
||||
watch_and_fix_permissions = partial(stylize_interface,fore_256='red',back_256='white', style=Style.BOLD)
|
||||
score_obj_det_orin = partial(stylize_interface, fore_256='red', back_256='green', style=Style.BOLD)
|
||||
remove_without_nuggets = partial(stylize_interface, fore_256='red', back_256='grey_78', style=Style.BOLD)
|
||||
embeds_in_db =partial(stylize_interface, fore_256='green', back_256='black', style=Style.BOLD)
|
||||
video_meta = partial(stylize_interface, fore_256='blue', back_256='black', style=Style.BOLD)
|
||||
37
takeSnapshot.py
Executable file
37
takeSnapshot.py
Executable file
@@ -0,0 +1,37 @@
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
import cv2
|
||||
import time
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
|
||||
cdate = datetime.now()
|
||||
try:
|
||||
base_path = cdate.strftime('/home/thebears/Videos/Winslow/%Y%m%d/snapshots/')
|
||||
prestr = base_path + cdate.strftime('%Y%m%d_%H%M%S')
|
||||
|
||||
if not os.path.exists(base_path):
|
||||
os.makedirs(base_path)
|
||||
|
||||
|
||||
video_obj = dict()
|
||||
video_obj[1] = cv2.VideoCapture('http://localhost:6082/frame.mjpg')
|
||||
video_obj[2] = cv2.VideoCapture('http://localhost:6083/frame.mjpg')
|
||||
video_obj[3] = cv2.VideoCapture('http://localhost:6084/frame.mjpg')
|
||||
video_obj[4] = cv2.VideoCapture('http://localhost:6085/frame.mjpg')
|
||||
video_obj[5] = cv2.VideoCapture('http://localhost:6086/frame.mjpg')
|
||||
|
||||
|
||||
for idx, obj in video_obj.items():
|
||||
filepath = prestr + '_' + str(idx) +'.jpg'
|
||||
print(filepath)
|
||||
(success, image) = obj.read()
|
||||
cv2.imwrite(filepath, image)
|
||||
obj.release()
|
||||
except Exception as E:
|
||||
print(E)
|
||||
|
||||
|
||||
time.sleep(15)
|
||||
1
test_dbconn.py
Normal file
1
test_dbconn.py
Normal file
@@ -0,0 +1 @@
|
||||
from CommonCode.db_conn import connect, db_api
|
||||
81
track.py
Executable file
81
track.py
Executable file
@@ -0,0 +1,81 @@
|
||||
from datetime import datetime, timedelta
|
||||
import redis
|
||||
r = redis.StrictRedis(host='192.168.1.242', port=6379, db=1)
|
||||
class BaseSensorPost(object):
|
||||
def __init__(self, sq, sensor_type, table,**kwargs):
|
||||
self.last_values = [None,None]
|
||||
self.last_measurement = None
|
||||
self.last_insert = datetime.utcnow()
|
||||
self.sq = sq
|
||||
self.heartbeat_interval = 15*60
|
||||
self.sensor = sensor_type
|
||||
self.table = table;
|
||||
self.kwargs = kwargs
|
||||
|
||||
def insert_heartbeat(self, time_init):
|
||||
return True
|
||||
# ins = self.sq['t'][self.table].insert().values(
|
||||
# when_timestamp = time_init, what = self.sensor)
|
||||
# self.sq['s'].execute(ins)
|
||||
|
||||
|
||||
class Temperature(BaseSensorPost):
|
||||
|
||||
def insert_temperature(self, time_init, temperature):
|
||||
if time_init is not None and temperature is not None:
|
||||
self.sq.executemany('INSERT INTO nuggets.temperature (when, temperature, where) values ',[{'when':time_init, 'temperature':temperature, 'where':self.kwargs['where']}])
|
||||
|
||||
# ins = self.sq['t'][self.table].insert().values(temperature = temperature, when_timestamp = time_init, where_id=self.kwargs['where'])
|
||||
# self.sq['s'].execute(ins)
|
||||
|
||||
|
||||
|
||||
def parse(self, time_init,string):
|
||||
string = string.strip(',');
|
||||
string = string.split(':')[1];
|
||||
curr_temp = float(string)
|
||||
self.insert_temperature(time_init, curr_temp)
|
||||
# self.insert_temperature(time_init,string)
|
||||
|
||||
# if (time_init - self.last_insert).seconds > self.heartbeat_interval:
|
||||
# self.insert_heartbeat(time_init)
|
||||
# self.last_insert = time_init
|
||||
|
||||
|
||||
|
||||
|
||||
class Odometer(BaseSensorPost):
|
||||
|
||||
def insert_speeds(self, time_init, transittime = None, heartbeat = False):
|
||||
|
||||
if transittime is None or transittime < 0:
|
||||
isclockwise = 0
|
||||
else:
|
||||
isclockwise = 1
|
||||
if time_init is not None:
|
||||
self.sq.executemany('INSERT INTO nuggets.odometer (when, who, speed, clockwise) values ',[{'when':time_init, 'who':self.kwargs['who'], 'speed':abs(transittime), 'clockwise':isclockwise}])
|
||||
|
||||
# ins = self.sq['t'][self.table].insert().values(
|
||||
# when_timestamp = time_init, speed = abs(transittime), who_id = self.kwargs['who'],
|
||||
# clockwise = isclockwise )
|
||||
# self.sq['s'].execute(ins)
|
||||
|
||||
|
||||
def parse(self, time_init,string):
|
||||
string = string.strip(',');
|
||||
string = string.split(':')[1];
|
||||
string = string.split(',')
|
||||
for speed, offset in zip(string[0::2],string[1::2]):
|
||||
speed = int(speed)
|
||||
if speed != 0:
|
||||
time_actual = time_init + timedelta(milliseconds = int(offset))
|
||||
self.insert_speeds(time_actual, transittime = speed)
|
||||
r.incr('nugget_run_counts')
|
||||
|
||||
if (time_init - self.last_insert).seconds > self.heartbeat_interval:
|
||||
self.insert_heartbeat(time_init )
|
||||
self.last_insert = time_init
|
||||
|
||||
self.last_measurement = time_init
|
||||
|
||||
# %%
|
||||
129
trackSerial.py
Executable file
129
trackSerial.py
Executable file
@@ -0,0 +1,129 @@
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
import traceback
|
||||
import syslog
|
||||
from db_conn import connect
|
||||
import dateutil.parser
|
||||
from datetime import timedelta, datetime, timezone
|
||||
sys.path.append('/home/thebears/Nextcloud/Designs/NuggetTracker/CommonCode/')
|
||||
from track import Temperature, VerticalWheel, ActivityLogger, Weight, BaseSensorPost, HorizontalWheel, Paired
|
||||
import os
|
||||
|
||||
sq = connect()
|
||||
|
||||
commit_interval = 60
|
||||
code_heartbeat = 10*60
|
||||
|
||||
def now():
|
||||
return datetime.now(timezone.utc)
|
||||
|
||||
last_commit = now()
|
||||
last_heartbeat = now()
|
||||
|
||||
func_ref = {'T:':Temperature(sq, 'floor2temperature'), 'V:':VerticalWheel(sq, 'verticalwheel'), 'M:':ActivityLogger(sq,'activities'),
|
||||
'W':Weight(sq,'food_weight'), 'S:':HorizontalWheel(sq, 'horizontalwheel'), 'D':ActivityLogger(sq,'food_dispenser'), 'A':Paired(sq,'food_forager')};
|
||||
|
||||
code_start = BaseSensorPost(sq, 'started')
|
||||
code_start.insert_heartbeat(now())
|
||||
|
||||
|
||||
heartbeat = BaseSensorPost(sq, 'code')
|
||||
|
||||
ser = serial.Serial('/dev/winslowMONITOR', 9600, timeout=None)
|
||||
#ser = serial.Serial('/dev/ttyACM0',57600,timeout=None)
|
||||
while True:
|
||||
try:
|
||||
if os.path.exists('/dev/shm/mealies_open.txt'):
|
||||
os.remove('/dev/shm/mealies_open.txt')
|
||||
ser.write(b'n')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_close.txt'):
|
||||
os.remove('/dev/shm/mealies_close.txt')
|
||||
ser.write(b'o')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_next.txt'):
|
||||
os.remove('/dev/shm/mealies_next.txt')
|
||||
ser.write(b'p')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/mealies2_open.txt'):
|
||||
os.remove('/dev/shm/mealies2_open.txt')
|
||||
ser.write(b'c')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies2_reset.txt'):
|
||||
os.remove('/dev/shm/mealies2_reset.txt')
|
||||
ser.write(b'd')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies2_open_all.txt'):
|
||||
os.remove('/dev/shm/mealies2_open_all.txt')
|
||||
ser.write(b'e')
|
||||
|
||||
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_reinit.txt'):
|
||||
os.remove('/dev/shm/mealies_reinit.txt')
|
||||
ser.write(b'q')
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/i2c_reinit.txt'):
|
||||
os.remove('/dev/shm/i2c_reinit.txt')
|
||||
ser.write(b'r')
|
||||
|
||||
if os.path.exists('/dev/shm/winslow/mealies2_reset.txt'):
|
||||
os.remove('/dev/shm/winslow/mealies2_reset.txt')
|
||||
ser.write(b'd')
|
||||
|
||||
except:
|
||||
e = traceback.format_exc()
|
||||
print(e)
|
||||
syslog.syslog(syslog.LOG_ERR,e)
|
||||
|
||||
|
||||
|
||||
|
||||
try:
|
||||
|
||||
data = ser.readline()
|
||||
string = data.decode('UTF-8')
|
||||
print(string)
|
||||
syslog.syslog(syslog.LOG_INFO,string)
|
||||
parse_str = string.strip()
|
||||
time_init = now()
|
||||
for startchars, function in func_ref.items():
|
||||
if parse_str.startswith(startchars):
|
||||
print(parse_str, function)
|
||||
function.parse(time_init,parse_str)
|
||||
|
||||
|
||||
sq['s'].commit()
|
||||
curr_time = now()
|
||||
if (curr_time - last_heartbeat).seconds > code_heartbeat:
|
||||
heartbeat.insert_heartbeat(curr_time)
|
||||
|
||||
|
||||
|
||||
except:
|
||||
e = traceback.format_exc()
|
||||
print(e)
|
||||
syslog.syslog(syslog.LOG_ERR,e)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
155
trackSerial_fullduplex (SFConflict ispatel@live.com 2025-06-22-10-59-32).py
Executable file
155
trackSerial_fullduplex (SFConflict ispatel@live.com 2025-06-22-10-59-32).py
Executable file
@@ -0,0 +1,155 @@
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
import traceback
|
||||
#from CommonCode.db_conn import connect
|
||||
import dateutil.parser
|
||||
from datetime import timedelta, datetime
|
||||
from pytz import timezone
|
||||
from CommonCode.track import Temperature, Odometer, BaseSensorPost
|
||||
import os
|
||||
import threading
|
||||
import redis
|
||||
|
||||
#sq = connect()
|
||||
r = redis.StrictRedis(host='192.168.1.242', port=6379, db=1)
|
||||
|
||||
def now():
|
||||
return datetime.now()
|
||||
# return datetime.now(timezone('US/Eastern'))
|
||||
|
||||
commit_interval = 60
|
||||
code_heartbeat = 10*60
|
||||
|
||||
last_commit = now()
|
||||
last_heartbeat = now()
|
||||
|
||||
#func_ref = {'T:':Temperature(sq, 'floor2temperature'), 'V:':VerticalWheel(sq, 'verticalwheel'), 'M:':ActivityLogger(sq,'activities'),
|
||||
# 'W':Weight(sq,'food_weight'), 'S:':HorizontalWheel(sq, 'horizontalwheel_sonic'), 'D':ActivityLogger(sq,'food_dispenser'), 'A':Paired(sq,'food_forager')};
|
||||
|
||||
|
||||
from clickhouse_driver import connect
|
||||
from datetime import datetime
|
||||
conn = connect('clickhouse://192.168.1.242');
|
||||
sq = conn.cursor();
|
||||
|
||||
|
||||
func_ref = {'T':Temperature(sq, 'floor_3_temperature','temperature',where=1),'S':Odometer(sq,'i2c_odometer','odometer',who=4)}
|
||||
code_start = BaseSensorPost(sq, 'started','heartbeats')
|
||||
code_start.insert_heartbeat(now())
|
||||
|
||||
|
||||
heartbeat = BaseSensorPost(sq, 'code','heartbeats')
|
||||
|
||||
ser = serial.Serial('/dev/serial_i2c', 9600, timeout=None)
|
||||
|
||||
def write():
|
||||
while True:
|
||||
time.sleep(0.2)
|
||||
try:
|
||||
if os.path.exists('/dev/shm/mealies_open.txt'):
|
||||
os.remove('/dev/shm/mealies_open.txt')
|
||||
ser.write(b'n')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_close.txt'):
|
||||
os.remove('/dev/shm/mealies_close.txt')
|
||||
ser.write(b'o')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_next.txt'):
|
||||
os.remove('/dev/shm/mealies_next.txt')
|
||||
ser.write(b'p')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/winslow/mealies2_open.txt'):
|
||||
os.remove('/dev/shm/winslow/mealies2_open.txt')
|
||||
ser.write(b'c')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies2_reset.txt'):
|
||||
os.remove('/dev/shm/mealies2_reset.txt')
|
||||
ser.write(b'd')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies2_open_all.txt'):
|
||||
os.remove('/dev/shm/mealies2_open_all.txt')
|
||||
ser.write(b'e')
|
||||
|
||||
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_reinit.txt'):
|
||||
os.remove('/dev/shm/mealies_reinit.txt')
|
||||
ser.write(b'q')
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/i2c_reinit.txt'):
|
||||
os.remove('/dev/shm/i2c_reinit.txt')
|
||||
ser.write(b'r')
|
||||
|
||||
if os.path.exists('/dev/shm/winslow/mealies2_reset.txt'):
|
||||
os.remove('/dev/shm/winslow/mealies2_reset.txt')
|
||||
ser.write(b'd')
|
||||
|
||||
except:
|
||||
e = traceback.format_exc()
|
||||
print(e)
|
||||
|
||||
|
||||
#t1 = threading.Thread(target=write, args=())
|
||||
#t1.start()
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
# try:
|
||||
if True:
|
||||
time.sleep(0.2)
|
||||
data = ser.readline()
|
||||
string = data.decode('UTF-8')
|
||||
print(string)
|
||||
parse_str = string.strip()
|
||||
time_init = now()
|
||||
for startchars, function in func_ref.items():
|
||||
if parse_str.startswith(startchars):
|
||||
r.set('i2c_'+startchars, str(time.time()) + ':' + parse_str)
|
||||
try:
|
||||
function.parse(time_init,parse_str)
|
||||
except IndexError:
|
||||
print('Index error')
|
||||
except Exception as ff:
|
||||
raise Exception(ff)
|
||||
|
||||
if (time_init - last_commit).seconds > commit_interval:
|
||||
# sq['s'].commit()
|
||||
last_commit = time_init
|
||||
|
||||
# sq['s'].commit()
|
||||
curr_time = now()
|
||||
if (curr_time - last_heartbeat).seconds > code_heartbeat:
|
||||
heartbeat.insert_heartbeat(curr_time)
|
||||
last_heartbeat = curr_time
|
||||
|
||||
last_heartbeat = curr_time
|
||||
|
||||
|
||||
|
||||
# except:
|
||||
# e = traceback.format_exc()
|
||||
# print(e)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
154
trackSerial_fullduplex.py
Executable file
154
trackSerial_fullduplex.py
Executable file
@@ -0,0 +1,154 @@
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
import traceback
|
||||
import syslog
|
||||
#from CommonCode.db_conn import connect
|
||||
import dateutil.parser
|
||||
from datetime import timedelta, datetime
|
||||
from pytz import timezone
|
||||
from CommonCode.track import Temperature, Odometer, BaseSensorPost
|
||||
import os
|
||||
import threading
|
||||
import redis
|
||||
|
||||
#sq = connect()
|
||||
r = redis.StrictRedis(host='192.168.1.242', port=6379, db=1)
|
||||
|
||||
def now():
|
||||
return datetime.now()
|
||||
# return datetime.now(timezone('US/Eastern'))
|
||||
|
||||
commit_interval = 60
|
||||
code_heartbeat = 10*60
|
||||
|
||||
last_commit = now()
|
||||
last_heartbeat = now()
|
||||
|
||||
#func_ref = {'T:':Temperature(sq, 'floor2temperature'), 'V:':VerticalWheel(sq, 'verticalwheel'), 'M:':ActivityLogger(sq,'activities'),
|
||||
# 'W':Weight(sq,'food_weight'), 'S:':HorizontalWheel(sq, 'horizontalwheel_sonic'), 'D':ActivityLogger(sq,'food_dispenser'), 'A':Paired(sq,'food_forager')};
|
||||
|
||||
|
||||
from clickhouse_driver import connect
|
||||
from datetime import datetime
|
||||
conn = connect('clickhouse://192.168.1.242');
|
||||
sq = conn.cursor();
|
||||
|
||||
|
||||
func_ref = {'T':Temperature(sq, 'floor_3_temperature','temperature',where=1),'S':Odometer(sq,'i2c_odometer','odometer',who=4)}
|
||||
code_start = BaseSensorPost(sq, 'started','heartbeats')
|
||||
code_start.insert_heartbeat(now())
|
||||
|
||||
|
||||
heartbeat = BaseSensorPost(sq, 'code','heartbeats')
|
||||
|
||||
ser = serial.Serial('/dev/serial_i2c', 9600, timeout=None)
|
||||
|
||||
def write():
|
||||
while True:
|
||||
time.sleep(0.2)
|
||||
try:
|
||||
if os.path.exists('/dev/shm/mealies_open.txt'):
|
||||
os.remove('/dev/shm/mealies_open.txt')
|
||||
ser.write(b'n')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_close.txt'):
|
||||
os.remove('/dev/shm/mealies_close.txt')
|
||||
ser.write(b'o')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_next.txt'):
|
||||
os.remove('/dev/shm/mealies_next.txt')
|
||||
ser.write(b'p')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/winslow/mealies2_open.txt'):
|
||||
os.remove('/dev/shm/winslow/mealies2_open.txt')
|
||||
ser.write(b'c')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies2_reset.txt'):
|
||||
os.remove('/dev/shm/mealies2_reset.txt')
|
||||
ser.write(b'd')
|
||||
|
||||
if os.path.exists('/dev/shm/mealies2_open_all.txt'):
|
||||
os.remove('/dev/shm/mealies2_open_all.txt')
|
||||
ser.write(b'e')
|
||||
|
||||
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/mealies_reinit.txt'):
|
||||
os.remove('/dev/shm/mealies_reinit.txt')
|
||||
ser.write(b'q')
|
||||
|
||||
|
||||
if os.path.exists('/dev/shm/i2c_reinit.txt'):
|
||||
os.remove('/dev/shm/i2c_reinit.txt')
|
||||
ser.write(b'r')
|
||||
|
||||
if os.path.exists('/dev/shm/winslow/mealies2_reset.txt'):
|
||||
os.remove('/dev/shm/winslow/mealies2_reset.txt')
|
||||
ser.write(b'd')
|
||||
|
||||
except:
|
||||
e = traceback.format_exc()
|
||||
print(e)
|
||||
syslog.syslog(syslog.LOG_ERR,e)
|
||||
|
||||
|
||||
t1 = threading.Thread(target=write, args=())
|
||||
t1.start()
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
try:
|
||||
# if True:
|
||||
time.sleep(0.2)
|
||||
data = ser.readline()
|
||||
string = data.decode('UTF-8')
|
||||
print(string)
|
||||
syslog.syslog(syslog.LOG_INFO,string)
|
||||
parse_str = string.strip()
|
||||
time_init = now()
|
||||
for startchars, function in func_ref.items():
|
||||
if parse_str.startswith(startchars):
|
||||
r.set('i2c_'+startchars, str(time.time()) + ':' + parse_str)
|
||||
function.parse(time_init,parse_str)
|
||||
|
||||
if (time_init - last_commit).seconds > commit_interval:
|
||||
# sq['s'].commit()
|
||||
last_commit = time_init
|
||||
|
||||
# sq['s'].commit()
|
||||
curr_time = now()
|
||||
if (curr_time - last_heartbeat).seconds > code_heartbeat:
|
||||
heartbeat.insert_heartbeat(curr_time)
|
||||
last_heartbeat = curr_time
|
||||
|
||||
last_heartbeat = curr_time
|
||||
|
||||
|
||||
|
||||
except:
|
||||
e = traceback.format_exc()
|
||||
print(e)
|
||||
syslog.syslog(syslog.LOG_ERR,e)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
112
util.py
Normal file
112
util.py
Normal file
@@ -0,0 +1,112 @@
|
||||
|
||||
import glob
|
||||
import json
|
||||
import textwrap
|
||||
import sys
|
||||
import os
|
||||
from collections import defaultdict
|
||||
def json_per_row_to_json(fpath = '/home/thebears/Videos/Winslow/saved/marks'):
|
||||
fid = open(fpath,'r')
|
||||
d = list()
|
||||
for x in fid:
|
||||
d.append(json.loads(x))
|
||||
|
||||
json.dump(d,open(fpath+'.json','w'),indent=4)
|
||||
|
||||
|
||||
def is_ipython():
|
||||
import __main__ as main_ff
|
||||
if hasattr(main_ff,'__file__'):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def exit_if_not_ipython():
|
||||
import __main__ as main_ff
|
||||
if hasattr(main_ff,'__file__'):
|
||||
print('Running in non-interactive mode, exiting...')
|
||||
sys.exit()
|
||||
else:
|
||||
print('Running in interactive mode, not exiting...')
|
||||
|
||||
|
||||
|
||||
def append_json_no_file_read(obj_append, jpath = '/home/thebears/Videos/Winslow/saved/marks.json'):
|
||||
fid = open(jpath,'r+')
|
||||
fid.seek(0,2)
|
||||
position = fid.tell() -2
|
||||
fid.seek(position)
|
||||
fid.write(",\n")
|
||||
fid.write(textwrap.indent(json.dumps(obj_append, indent=4),' '))
|
||||
fid.write('\n]')
|
||||
fid.close()
|
||||
|
||||
|
||||
|
||||
def get_cset_match(input_in):
|
||||
if not os.path.exists(input_in):
|
||||
return {}
|
||||
|
||||
if os.path.isdir(input_in):
|
||||
return get_cset_match_dir(input_in)
|
||||
else:
|
||||
dir_list = os.path.dirname(input_in)
|
||||
summ = get_cset_match_dir(dir_list)
|
||||
name, ext = os.path.splitext(input_in)
|
||||
tstamp = int(name.replace('_trimmed','').split('_')[-1])
|
||||
return summ[tstamp]
|
||||
|
||||
def get_cset_for_file_matching(file_in):
|
||||
name, ext = os.path.splitext(file_in)
|
||||
cset = dict()
|
||||
files = glob.glob(name+"*")
|
||||
for f in files:
|
||||
[f_name, f_ext ] =f.split(".",1)
|
||||
cset['.'+f_ext] = f
|
||||
|
||||
return cset
|
||||
|
||||
|
||||
def get_cset_match_dir(rtdir):
|
||||
summary = dict()
|
||||
|
||||
other_files = dict()
|
||||
|
||||
for f in os.walk(rtdir):
|
||||
c_rt = f[0]
|
||||
c_files = f[2]
|
||||
|
||||
for c_file in c_files:
|
||||
name, ext = os.path.splitext(c_file)
|
||||
try:
|
||||
tstamp = int(name.replace('_trimmed','').split('_')[-1])
|
||||
if ext in {'.mp4'}:
|
||||
summary[tstamp] = dict()
|
||||
summary[tstamp][ext] = os.path.join(c_rt, c_file)
|
||||
else:
|
||||
if tstamp not in other_files:
|
||||
other_files[tstamp] = dict()
|
||||
other_files[tstamp][ext] = os.path.join(c_rt, c_file)
|
||||
except:
|
||||
pass
|
||||
|
||||
mp4_tstamps = sorted(summary)
|
||||
other_tstamps = sorted(other_files)
|
||||
idx_other = 0
|
||||
|
||||
merge_map = defaultdict(list)
|
||||
merged = 0
|
||||
for idx_mp4, m_t in enumerate(mp4_tstamps):
|
||||
# for idx_o_test in range(len(other_tstamps)))
|
||||
for idx_o_test, o_t in enumerate(other_tstamps):
|
||||
if abs(m_t - o_t) < 25:
|
||||
merge_map[m_t].append(o_t)
|
||||
|
||||
|
||||
|
||||
for k, v in merge_map.items():
|
||||
for v_join in v:
|
||||
summary[k].update(other_files[v_join])
|
||||
|
||||
|
||||
return summary
|
||||
199
video_meta.py
Normal file
199
video_meta.py
Normal file
@@ -0,0 +1,199 @@
|
||||
import datetime as dt
|
||||
import os
|
||||
import numpy as np
|
||||
import subprocess
|
||||
import pickle
|
||||
from CommonCode.settings import get_logger, LogColorize
|
||||
import logging
|
||||
import numpy
|
||||
pfm = LogColorize.video_meta
|
||||
|
||||
if not ('__file__' in vars() or '__file__' in globals()):
|
||||
__file__ = '/home/thebears/Seafile/Designs/Code/Python/VideoProcessing/VideoMeta.py'
|
||||
|
||||
logger = get_logger(__name__, stdout=True, systemd=False)
|
||||
|
||||
orig_prefices = ("/srv/ftp", "/srv/ftp_tcc")
|
||||
new_prefices = "/mnt/hdd_24tb_1/videos/ftp"
|
||||
|
||||
|
||||
def get_info_from_ftp_filename(cpath):
|
||||
date_str_format = "%Y%m%d%H%M%S"
|
||||
bname = os.path.basename(cpath)
|
||||
froot, ext = os.path.splitext(bname)
|
||||
cam_name, index, time_str = froot.split("_")
|
||||
time_stamp = dt.datetime.strptime(time_str, date_str_format)
|
||||
file_info = {
|
||||
"name": cam_name,
|
||||
"index": index,
|
||||
"timestamp": time_stamp,
|
||||
"path": os.path.abspath(cpath),
|
||||
}
|
||||
return file_info
|
||||
|
||||
def get_cache_loc(cpath):
|
||||
fpathroot, ext = os.path.splitext(cpath)
|
||||
return fpathroot + '.timestamp_cache'
|
||||
|
||||
|
||||
class FTPVideo:
|
||||
def __init__(self, cpath):
|
||||
self.cpath = cpath
|
||||
self.file_info = get_info_from_ftp_filename(cpath)
|
||||
self._real_path = None
|
||||
self._frame_info = None
|
||||
self._embeds = None
|
||||
self._embed_scores = None
|
||||
|
||||
def __lt__(self, other):
|
||||
comp_val = other;
|
||||
if hasattr(other, 'timestamp'):
|
||||
comp_val = other.timestamp
|
||||
|
||||
return self.timestamp < comp_val
|
||||
|
||||
@staticmethod
|
||||
def vec_norm(vec_in):
|
||||
return vec_in / np.linalg.norm(vec_in, axis=1)[:,None]
|
||||
|
||||
@property
|
||||
def embed_scores(self):
|
||||
return self._embed_scores
|
||||
|
||||
def attach_embedding_score(self, scores):
|
||||
self._embed_scores = scores
|
||||
|
||||
|
||||
@property
|
||||
def embeddings(self):
|
||||
embeds_path = os.path.splitext(self.real_path)[0] + '.oclip_embeds.npz'
|
||||
if not os.path.exists(embeds_path):
|
||||
return None
|
||||
|
||||
if self._embeds is None:
|
||||
npz_contents = np.load(embeds_path)
|
||||
self._embeds = npz_contents
|
||||
|
||||
npz_contents = self._embeds
|
||||
|
||||
ret_dict = {};
|
||||
ret_dict['embeds'] = npz_contents['embeds']
|
||||
|
||||
ret_dict['frame_numbers'] = [int(x) for x in npz_contents['frame_numbers']]
|
||||
ret_dict['frame_offsets'] = [self.frames_info[x]['offset'] for x in ret_dict['frame_numbers']]
|
||||
ret_dict['frame_time'] = [self.frames_info[x]['time'] for x in ret_dict['frame_numbers']]
|
||||
e_scores = self.embed_scores
|
||||
if self.embed_scores is not None:
|
||||
ret_dict['embed_scores'] = e_scores
|
||||
|
||||
|
||||
return ret_dict
|
||||
|
||||
def try_cache_read(self):
|
||||
cache_loc = get_cache_loc(self.real_path)
|
||||
if os.path.exists(cache_loc):
|
||||
logger.info(pfm(f'ATTEMPT READING FROM CACHE: {cache_loc}'))
|
||||
try:
|
||||
with open(cache_loc,'rb') as ff:
|
||||
data = pickle.load(ff)
|
||||
logger.info(pfm(f'READ FROM CACHE: {cache_loc}'))
|
||||
return data
|
||||
except Exception as e:
|
||||
logger.warn(pfm(f'READ FROM CACHE FAILED: {e} while reading {cache_loc}'))
|
||||
|
||||
|
||||
return None
|
||||
|
||||
def try_cache_write(self, data):
|
||||
cache_loc = get_cache_loc(self.real_path)
|
||||
logger.info(pfm(f'ATTEMPTING WRITING TO CACHE: {cache_loc}'))
|
||||
try:
|
||||
with open(cache_loc, 'wb') as ff:
|
||||
pickle.dump(data, ff)
|
||||
logger.info(pfm(f'WROTE TO CACHE: {cache_loc}'))
|
||||
except Exception as e:
|
||||
logger.warn(pfm(f'WRITE TO CACHE FAILED: {e} while writing {cache_loc}'))
|
||||
|
||||
|
||||
@property
|
||||
def frames_info(self):
|
||||
if self._frame_info is None:
|
||||
self._frame_info = self.try_cache_read();
|
||||
|
||||
if self._frame_info is not None:
|
||||
return self._frame_info
|
||||
|
||||
self._frame_info = self.get_frames_info()
|
||||
self.try_cache_write(self._frame_info)
|
||||
|
||||
return self._frame_info
|
||||
|
||||
def get_frames_info(self):
|
||||
if self._frame_info is not None:
|
||||
return self._frame_info
|
||||
|
||||
fpath = self.real_path
|
||||
cmd = f"ffprobe -select_streams v:0 -show_entries packet=pts_time,flags -of csv {fpath}"
|
||||
logger.info(pfm(f'RUNNING FFPROBE FOR {fpath}'))
|
||||
|
||||
try:
|
||||
out = subprocess.check_output(cmd.split(), stderr=subprocess.DEVNULL)
|
||||
except Exception as e:
|
||||
logger.warn(pfm(f'RUNNING FFPROBE FAILED FOR {e} on {fpath}'))
|
||||
|
||||
logger.info(pfm(f'RAN FFPROBE SUCCESSFULLY FOR {fpath}'))
|
||||
|
||||
timestamps = list()
|
||||
for line in out.decode("UTF-8").split("\n"):
|
||||
if "," not in line:
|
||||
continue
|
||||
|
||||
_, fr_s, fr_type = line.split(",")
|
||||
fr_s = float(fr_s)
|
||||
|
||||
timestamps.append(
|
||||
{
|
||||
"offset": fr_s,
|
||||
"type": fr_type,
|
||||
"time": dt.timedelta(seconds=fr_s) + self.timestamp,
|
||||
}
|
||||
)
|
||||
|
||||
self._frame_info = timestamps
|
||||
return timestamps
|
||||
|
||||
@property
|
||||
def timestamp(self):
|
||||
return self.file_info["timestamp"]
|
||||
|
||||
@property
|
||||
def camera_name(self):
|
||||
return self.file_info["name"]
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
return self.cpath
|
||||
|
||||
@property
|
||||
def real_path(self):
|
||||
if self._real_path is not None:
|
||||
logger.debug(pfm(f'FOUND REAL PATH AS {self._real_path}'))
|
||||
return self._real_path
|
||||
|
||||
|
||||
|
||||
cand_path = self.path
|
||||
if os.path.exists(self.path):
|
||||
self._real_path = cand_path
|
||||
return cand_path
|
||||
for og_p in orig_prefices:
|
||||
for new_p in new_prefices:
|
||||
new_cand_path = cand_path.replace(og_p, new_p)
|
||||
logger.debug(pfm(f'TRYING PATH AS {new_cand_path}'))
|
||||
if os.path.exists(new_cand_path):
|
||||
self._real_path = new_cand_path
|
||||
logger.debug(pfm(f'FOUND REAL PATH AS {new_cand_path}'))
|
||||
return new_cand_path
|
||||
|
||||
|
||||
|
||||
96
wq.py
Normal file
96
wq.py
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python
|
||||
import redis, pickle
|
||||
from enum import Enum
|
||||
import json
|
||||
|
||||
class TOPICS(Enum):
|
||||
ml_vision_to_score = 'ml_vision_to_score'
|
||||
ml_vision_to_score_ext = 'ml_vision_to_score_ext'
|
||||
ml_vision_objdet_failed = 'ml_vision_objdet_failed'
|
||||
ml_vision_objdet_success = 'ml_vision_objdet_success'
|
||||
ml_vision_objdet_skipped = 'ml_vision_objdet_skipped'
|
||||
ml_vision_objdet_results_db_success = 'ml_vision_objdet_db_upload_success'
|
||||
ml_vision_objdet_results_db_failed = 'ml_vision_objdet_db_upload_failed'
|
||||
ml_vision_objdet_results_pg_success = 'ml_vision_objdet_pg_upload_success'
|
||||
ml_vision_objdet_results_pg_failed = 'ml_vision_objdet_pg_upload_failed'
|
||||
ml_vision_objdet_results_purge_success = 'ml_vision_objdet_purge_success'
|
||||
ml_vision_objdet_results_purge_failed = 'ml_vision_objdet_purge_failed'
|
||||
ml_vision_objdet_results_purge_skipped = 'ml_vision_objdet_purge_skipped'
|
||||
ml_vision_videos_modify_success = 'ml_vision_videos_modify_success'
|
||||
ml_vision_videos_modify_failed = 'ml_vision_videos_modify_failed'
|
||||
ml_vision_embedding_success = 'ml_vision_embedding_success'
|
||||
ml_vision_embedding_fail = 'ml_vision_embedding_fail'
|
||||
ml_vision_embedding_skipped = 'ml_vision_embedding_skipped'
|
||||
|
||||
|
||||
r = redis.StrictRedis()
|
||||
|
||||
def publish(topic, message):
|
||||
if isinstance(topic, TOPICS):
|
||||
topic = topic.value
|
||||
|
||||
|
||||
if isinstance(message, str):
|
||||
r.rpush(topic, message)
|
||||
else:
|
||||
r.rpush(topic, json.dumps(message))
|
||||
|
||||
|
||||
def parse_message(msg):
|
||||
try:
|
||||
return json.loads(msg)
|
||||
except:
|
||||
return msg.decode()
|
||||
|
||||
def consume(topic):
|
||||
if isinstance(topic, TOPICS):
|
||||
topic = topic.value
|
||||
|
||||
msg = r.rpop(topic)
|
||||
if msg is None:
|
||||
return None
|
||||
else:
|
||||
return parse_message(msg)
|
||||
|
||||
def peek(topic):
|
||||
if isinstance(topic, TOPICS):
|
||||
topic = topic.value
|
||||
|
||||
vals = r.lrange(topic,0, 0)
|
||||
if len(vals) == 0:
|
||||
return None
|
||||
else:
|
||||
return parse_message(vals[0])
|
||||
|
||||
# from kafka import KafkaProducer, KafkaConsumer
|
||||
# import pickle
|
||||
|
||||
# producer = KafkaProducer(bootstrap_servers=["192.168.1.242:9092"])
|
||||
# consumers = dict()
|
||||
# # %%
|
||||
|
||||
# def publish(topic, message):
|
||||
# producer.send(topic, value=pickle.dumps(message))
|
||||
# producer.flush()
|
||||
|
||||
|
||||
# def get_consumer_by_topic(topic):
|
||||
# if topic in consumers:
|
||||
# return consumers[topic]
|
||||
|
||||
# csumer = KafkaConsumer(
|
||||
# bootstrap_servers="localhost:9092",
|
||||
# group_id="wq",
|
||||
# auto_offset_reset="earliest",
|
||||
# enable_auto_commit=True,
|
||||
# consumer_timeout_ms=1000,
|
||||
# )
|
||||
# csumer.subscribe(topic)
|
||||
# consumers[topic] = csumer
|
||||
|
||||
|
||||
# def get_a_message(topic):
|
||||
# csumer = get_consumer_by_topic(topic)
|
||||
# return csumer
|
||||
|
||||
|
||||
Reference in New Issue
Block a user