Add MetricsLogging

This commit is contained in:
Konstantin Lampalzer 2021-09-06 18:51:52 +02:00
parent 60f252c37a
commit 3fe3139961
6 changed files with 168 additions and 61 deletions

View file

@ -2,6 +2,7 @@ import atexit
from enum import Enum from enum import Enum
from compLib.LogstashLogging import Logging from compLib.LogstashLogging import Logging
from compLib.MetricsLogging import MetricsLogging
from compLib.Spi import Spi, Register from compLib.Spi import Spi, Register
MOTOR_COUNT = 4 MOTOR_COUNT = 4
@ -47,7 +48,8 @@ class Encoder(object):
diff = Encoder.read_raw(port) - encoder_start_values[port] diff = Encoder.read_raw(port) - encoder_start_values[port]
if diff > 2 ** 31: if diff > 2 ** 31:
diff -= 2 ** 32 diff -= 2 ** 32
MetricsLogging.put("Encoder", diff, port)
return diff return diff
@staticmethod @staticmethod

View file

@ -1,6 +1,6 @@
from compLib.LogstashLogging import Logging from compLib.LogstashLogging import Logging
from compLib.MetricsLogging import MetricsLogging
from compLib.Spi import Spi, Register from compLib.Spi import Spi, Register
import spidev
SENSOR_COUNT = 5 SENSOR_COUNT = 5
@ -14,18 +14,20 @@ class IRSensor(object):
if sensor <= 0 or sensor > SENSOR_COUNT: if sensor <= 0 or sensor > SENSOR_COUNT:
raise IndexError("Invalid sensor specified!") raise IndexError("Invalid sensor specified!")
result = 0
if sensor == 1: if sensor == 1:
return Spi.read(Register.IR_1_H, 2) result = Spi.read(Register.IR_1_H, 2)
elif sensor == 2: elif sensor == 2:
return Spi.read(Register.IR_2_H, 2) esult = Spi.read(Register.IR_2_H, 2)
elif sensor == 3: elif sensor == 3:
return Spi.read(Register.IR_3_H, 2) esult = Spi.read(Register.IR_3_H, 2)
elif sensor == 4: elif sensor == 4:
return Spi.read(Register.IR_4_H, 2) esult = Spi.read(Register.IR_4_H, 2)
elif sensor == 5: elif sensor == 5:
return Spi.read(Register.IR_5_H, 2) esult = Spi.read(Register.IR_5_H, 2)
else:
return 0 MetricsLogging.put("Infrared", result, sensor)
return result
@staticmethod @staticmethod
def set(sensor: int, on: bool): def set(sensor: int, on: bool):

84
compLib/MetricsLogging.py Normal file
View file

@ -0,0 +1,84 @@
from influxdb_client import InfluxDBClient, Point, WritePrecision
import socket
import uuid
import os
import queue
import datetime
import threading
import requests
CONCURRENCY = 2
HOSTNAME = socket.gethostname()
RUN_TRACE = str(uuid.uuid4())
TOKEN = "aCdxnntw-Zp3agci8Z32lQAR_ep6MhdmWOJG7ObnoikYqe7nKAhFYx1jVGBpipQuId79SC4Jl0J6IBYVqauJyw=="
ORG = "robo4you"
BUCKET = "compAIR"
INFLUX_HOST = "https://influxdb.comp-air.at"
EXTENSIVE_LOGGING = os.getenv("EXTENSIVE_LOGGING", "True")
if EXTENSIVE_LOGGING == "True":
EXTENSIVE_LOGGING = True
else:
EXTENSIVE_LOGGING = False
influx_client = InfluxDBClient(url=INFLUX_HOST, token=TOKEN)
write_api = influx_client.write_api()
point_queue = queue.Queue()
workers = []
class MetricsLogging():
@staticmethod
def is_influx_reachable():
try:
r = requests.get(INFLUX_HOST)
if r.status_code == 200:
return True
else:
print(f"Could not connect to {INFLUX_HOST} -> ERROR CODE: {r.status_code}!")
return False
except requests.exceptions.RequestException as identifier:
print(f"Could not connect to {INFLUX_HOST}!")
@staticmethod
def put(sensorType, value, port):
if EXTENSIVE_LOGGING:
point = Point(sensorType) \
.tag("host", HOSTNAME) \
.tag("runID", RUN_TRACE) \
.tag("port", port) \
.field("value", value) \
.time(datetime.datetime.utcnow(), WritePrecision.MS)
point_queue.put_nowait(point)
@staticmethod
def worker():
while True:
point = point_queue.get()
if point is None: # Kill signal
return
try:
write_api.write(BUCKET, ORG, point)
finally:
point_queue.task_done()
@staticmethod
def start_workers():
global EXTENSIVE_LOGGING
if EXTENSIVE_LOGGING:
if MetricsLogging.is_influx_reachable():
EXTENSIVE_LOGGING = False
for i in range(CONCURRENCY):
worker = threading.Thread(target=MetricsLogging.worker, daemon=True)
worker.start()
workers.append(worker)
MetricsLogging.start_workers()

View file

@ -2,6 +2,7 @@ import atexit
from enum import IntEnum from enum import IntEnum
from compLib.LogstashLogging import Logging from compLib.LogstashLogging import Logging
from compLib.MetricsLogging import MetricsLogging
from compLib.Spi import Spi, Register from compLib.Spi import Spi, Register
MOTOR_COUNT = 4 MOTOR_COUNT = 4
@ -45,14 +46,13 @@ class Motor(object):
Spi.write(Register.PWM_4_CTRL, 1, int(mode)) Spi.write(Register.PWM_4_CTRL, 1, int(mode))
@staticmethod @staticmethod
def power_raw(port: int, percent: float): def power_raw(port: int, percent: float, log_metric = True):
"""Set specified motor to percentage power """Set specified motor to percentage power
:param port: Port, which the motor is connected to. 1-4 :param port: Port, which the motor is connected to. 1-4
:param percent: Percentage of max speed. between -100 and 100 :param percent: Percentage of max speed. between -100 and 100
:raises: IndexError :raises: IndexError
""" """
Logging.get_logger().debug(f"Motor.power {port} {percent}")
if port <= 0 or port > MOTOR_COUNT: if port <= 0 or port > MOTOR_COUNT:
raise IndexError("Invalid Motor port specified!") raise IndexError("Invalid Motor port specified!")
@ -60,6 +60,9 @@ class Motor(object):
if percent < -100 or percent > 100: if percent < -100 or percent > 100:
raise IndexError("Invalid Motor speed specified! Speed is between -100 and 100 percent!") raise IndexError("Invalid Motor speed specified! Speed is between -100 and 100 percent!")
if log_metric:
MetricsLogging.put("MotorRaw", percent, port)
mode = MotorMode.COAST mode = MotorMode.COAST
if percent < 0: if percent < 0:
percent = abs(percent) percent = abs(percent)
@ -80,12 +83,14 @@ class Motor(object):
:param percent: Percentage of max speed. between -100 and 100 :param percent: Percentage of max speed. between -100 and 100
:raises: IndexError :raises: IndexError
""" """
raw_power = 0
if percent > 0: if percent > 0:
Motor.power_raw(port, Motor.__linearizePower(MOTOR_CURVE, percent)) raw_power = Motor.__linearizePower(MOTOR_CURVE, percent)
elif percent < 0: elif percent < 0:
Motor.power_raw(port, -Motor.__linearizePower(MOTOR_CURVE, -percent)) raw_power = -Motor.__linearizePower(MOTOR_CURVE, -percent)
else:
Motor.power_raw(port, 0) MetricsLogging.put("Motor", percent, port, False)
Motor.power_raw(port, raw_power)
@staticmethod @staticmethod
def all_off(): def all_off():

View file

@ -1,36 +1,36 @@
from compLib.PCA9685 import PCA9685 # from compLib.PCA9685 import PCA9685
SERVO_COUNT = 10 # SERVO_COUNT = 10
pwm = PCA9685(0x40, debug=True) # pwm = PCA9685(0x40, debug=True)
pwm.setPWMFreq(50) # pwm.setPWMFreq(50)
MIN_ANGLE = -90.0 # MIN_ANGLE = -90.0
MAX_ANGLE = 90.0 # MAX_ANGLE = 90.0
class Servo: # class Servo:
"""Control the servo ports on the robot # """Control the servo ports on the robot
""" # """
@staticmethod # @staticmethod
def set_position(channel: int, angle: int, offset: float =90): # def set_position(channel: int, angle: int, offset: float =90):
"""Set position of servo connected to port # """Set position of servo connected to port
:param channel: channel between 0 and 7 # :param channel: channel between 0 and 7
:param angle: Angle of servo # :param angle: Angle of servo
""" # """
if channel < 0 or channel >= SERVO_COUNT: # if channel < 0 or channel >= SERVO_COUNT:
raise IndexError("Invalid Servo channel specified!") # raise IndexError("Invalid Servo channel specified!")
angle = max(min(angle, MAX_ANGLE), MIN_ANGLE) # angle = max(min(angle, MAX_ANGLE), MIN_ANGLE)
pwm.setServoPulse(channel + 8, 500+int((angle+offset)/0.09)) # pwm.setServoPulse(channel + 8, 500+int((angle+offset)/0.09))
@staticmethod # @staticmethod
def setup_position(): # def setup_position():
"""Set position of servos to the position used during the setup process # """Set position of servos to the position used during the setup process
""" # """
Servo.set_position(0, 0) # Servo.set_position(0, 0)
Servo.set_position(1, 0) # Servo.set_position(1, 0)

View file

@ -1,26 +1,40 @@
__version__ = "0.1.5-1" __version__ = "0.1.5-1"
import importlib
import compLib.LogstashLogging import compLib.LogstashLogging
import compLib.Spi
import compLib.Reset
import compLib.Encoder
import logging
import apt
try:
__versions = apt.Cache()["python3-complib"].versions
if len(__versions) != 1:
print(f"Starting compLib! \033[91mVersion: {__version__} is outdated\033[0m\n"
f"\033[92m[!] run the command 'sudo apt update && sudo apt install python3-complib' to install the newest version\033[0m")
else:
print(f"Starting compLib! \033[92mVersion: {__version__} is up to date\033[0m")
except Exception as e:
compLib.LogstashLogging.Logging.get_logger().error(f"error during checking apt package version -> {str(e)}")
print(f"\033[91merror during checking apt package version -> {str(e)}\033[0m\n")
print(f"\033[34mInitializing chipmunk board...\033[0m") apt_found = importlib.util.find_spec("apt") is not None
compLib.Reset.Reset.reset_bot() spi_found = importlib.util.find_spec("spidev") is not None
compLib.Spi.Spi.health_check()
compLib.Spi.Spi.start_health_check_loop()
compLib.Encoder.Encoder.clear_all() if apt_found:
print(f"\033[34mReady\033[0m\n") import apt
try:
__versions = apt.Cache()["python3-complib"].versions
if len(__versions) != 1:
print(f"Starting compLib! \033[91mVersion: {__version__} is outdated\033[0m\n"
f"\033[92m[!] run the command 'sudo apt update && sudo apt install python3-complib' to install the newest version\033[0m")
else:
print(f"Starting compLib! \033[92mVersion: {__version__} is up to date\033[0m")
except Exception as e:
compLib.LogstashLogging.Logging.get_logger().error(f"error during checking apt package version -> {str(e)}")
print(f"\033[91merror during checking apt package version -> {str(e)}\033[0m\n")
else:
print("apt is not installed! This is for local development only!")
if spi_found:
import compLib.Spi
import compLib.Reset
import compLib.Encoder
import logging
print(f"\033[34mInitializing chipmunk board...\033[0m")
compLib.Reset.Reset.reset_bot()
compLib.Spi.Spi.health_check()
compLib.Spi.Spi.start_health_check_loop()
compLib.Encoder.Encoder.clear_all()
print(f"\033[34mReady\033[0m\n")
else:
print("spidev is not installed! This is for local development only!")