Compare commits

...

12 Commits

@ -16,34 +16,6 @@ import shepherd.plugin
#Start new thread, and push ID and core config to api.shepherd.distreon.net/client/update #Start new thread, and push ID and core config to api.shepherd.distreon.net/client/update
class UpdateManager():
def __init__(self):
pass
class SequenceUpdate():
Item = namedtuple('Item', ['sequence_number', 'content'])
def __init__(self):
self.items = []
self._sequence_count = 0
self._dirty = False
def _next_sequence_number(self):
# TODO: need to establish a max sequence number, so that it can be compared to half
# that range and wrap around.
self._sequence_count +=1
return self._sequence_count
def mark_as_dirty(self):
self._dirty = True
def add_item(self, item):
self.items.append(self.Item(self._next_sequence_number(), item))
self.mark_as_dirty()
def get_payload():
pass
def process_ack():
pass
client_id = None client_id = None
control_url = None control_url = None

@ -169,30 +169,29 @@ def compile_config(default_config_path):
return core_conf, plugin_classes, plugin_configs return core_conf, plugin_classes, plugin_configs
@click.group(invoke_without_command = True) @click.group(invoke_without_command=True)
#help="Path to default config TOML file" #help="Path to default config TOML file"
@click.argument('default_config', default="shepherd-default.toml", type=click.Path()) @click.argument('default_config', default="shepherd-default.toml", type=click.Path())
@click.pass_context @click.pass_context
def cli(ctx, default_config): def cli(ctx, default_config):
""" """
Core service. Expects the default config to be set as an argument. Core service. Expects the default config to be set as an argument.
""" """
#argparser = argparse.ArgumentParser(description="Keep track of a mob " # argparser = argparse.ArgumentParser(description="Keep track of a mob "
# "of roaming Pis") # "of roaming Pis")
#argparser.add_argument("configfile", nargs='?', metavar="configfile", # argparser.add_argument("configfile", nargs='?', metavar="configfile",
# help="Path to configfile", default="shepherd.toml") # help="Path to configfile", default="shepherd.toml")
#argparser.add_argument( # argparser.add_argument(
# '-e', '--noedit', help="Disable the editable config temporarily", action="store_true", default=False) # '-e', '--noedit', help="Disable the editable config temporarily", action="store_true", default=False)
#argparser.add_argument("-t", "--test", help="Test and interface function of the from 'plugin:function'", # argparser.add_argument("-t", "--test", help="Test and interface function of the from 'plugin:function'",
# default=None) # default=None)
#args = argparser.parse_args() #args = argparser.parse_args()
core_conf, plugin_classes, plugin_configs = compile_config(default_config) core_conf, plugin_classes, plugin_configs = compile_config(default_config)
if args.test is None: # if args.test is None:
control.init_control(core_conf, plugin_configs) # control.init_control(core_conf, plugin_configs)
scheduler.init_scheduler(core_conf) scheduler.init_scheduler(core_conf)
plugin.init_plugins(plugin_classes, plugin_configs, core_conf) plugin.init_plugins(plugin_classes, plugin_configs, core_conf)
@ -209,11 +208,11 @@ def cli(ctx, default_config):
except (KeyboardInterrupt, SystemExit): except (KeyboardInterrupt, SystemExit):
pass pass
@click.argument('plugin_function') @click.argument('plugin_function')
@cli.command() @cli.command()
def test(): def test(plugin_function):
if args.test is not None: (test_plugin, test_func) = plugin_function.split(':')
(test_plugin, test_func) = args.test.split(':') func = getattr(plugin.plugin_functions[test_plugin], test_func)
func = getattr(shepherd.plugin.plugin_functions[test_plugin], test_func)
print(func()) print(func())
return return

@ -1,77 +1,48 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import shepherd.config import shepherd.config as shconf
import shepherd.module import shepherd.plugin
import sys import sys
import os import os
import time import time
import argparse import argparse
from gpiozero import OutputDevice, Device
from gpiozero.pins.pigpio import PiGPIOFactory
from shepherd.modules.betterservo import BetterServo class AphidtrapModule(shepherd.plugin.Plugin):
@staticmethod
def define_config(confdef):
pass
Device.pin_factory = PiGPIOFactory() def __init__(self, pluginInterface, config):
super().__init__(pluginInterface, config)
self.config = config
APHIDTRAP_LED_PIN = 5 #Out2 self.interface = pluginInterface
self.plugins = pluginInterface.other_plugins
self.hooks = pluginInterface.hooks
class AphidtrapConfDef(shepherd.config.ConfDefinition):
def __init__(self):
super().__init__()
class AphidtrapModule(shepherd.module.SimpleModule):
conf_def = AphidtrapConfDef()
def setup(self):
print("Aphidtrap config:") print("Aphidtrap config:")
print(self.config) print(self.config)
self.led_power = OutputDevice(APHIDTRAP_LED_PIN, if "picam" in self.plugins:
active_high=True, self.interface.attach_hook("picam", "pre_cam", self.led_on)
initial_value=False) self.interface.attach_hook("picam", "post_cam", self.led_off)
elif "usbcam" in self.plugins:
self.interface.attach_hook("usbcam", "pre_cam", self.led_on)
self.interface.attach_hook("usbcam", "post_cam", self.led_off)
else:
raise ValueError("Need to either have picam or usbcam plugin loaded")
def setup_other_modules(self): self.interface.register_function(self.test)
self.modules.picam.hook_pre_cam.attach(self.led_on)
self.modules.picam.hook_post_cam.attach(self.led_off)
def led_on(self): def led_on(self):
self.led_power.on() self.plugins["scout"].set_out2(True)
def led_off(self): def led_off(self):
self.led_power.off() self.plugins["scout"].set_out2(False)
def main(argv): def test(self):
argparser = argparse.ArgumentParser( self.led_on()
description='Module for aphidtrap control functions. Run for testing')
argparser.add_argument("configfile", nargs='?', metavar="configfile",
help="Path to configfile", default="conf.toml")
args = argparser.parse_args()
confman = shepherd.config.ConfigManager()
srcdict = {"aphidtrap": {}}
if os.path.isfile(args.configfile):
confman.load(args.configfile)
else:
confman.load(srcdict)
aphidtrap_mod = AphidtrapModule(confman.get_config("aphidtrap", AphidtrapConfDef()),
shepherd.module.Interface(None))
aphidtrap_mod.led_on()
time.sleep(2) time.sleep(2)
aphidtrap_mod.led_off() self.led_off()
if __name__ == "__main__":
main(sys.argv[1:])

@ -25,7 +25,7 @@ class FlytrapPlugin(shepherd.plugin.Plugin):
self.hooks = pluginInterface.hooks self.hooks = pluginInterface.hooks
self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"]) self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"])
self.id = pluginInterface.coreconfig["id"] self.id = pluginInterface.coreconfig["name"]
print("Flytrap config:") print("Flytrap config:")
print(self.config) print(self.config)

@ -9,7 +9,6 @@ import time
import argparse import argparse
class MothtrapPlugin(shepherd.plugin.Plugin): class MothtrapPlugin(shepherd.plugin.Plugin):
@staticmethod @staticmethod
def define_config(confdef): def define_config(confdef):
@ -25,40 +24,43 @@ class MothtrapPlugin(shepherd.plugin.Plugin):
self.hooks = pluginInterface.hooks self.hooks = pluginInterface.hooks
self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"]) self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"])
self.id = pluginInterface.coreconfig["id"] self.id = pluginInterface.coreconfig["name"]
print("Mothtrap config:") print("Mothtrap config:")
print(self.config) print(self.config)
#servo_max = self.config["servo_open_pulse"] / 1000000 #servo_max = self.config["servo_open_pulse"] / 1000000
#servo_min = self.config["servo_closed_pulse"] / 1000000 #servo_min = self.config["servo_closed_pulse"] / 1000000
#if servo_min > servo_max: # if servo_min > servo_max:
# servo_min, servo_max = servo_max, servo_min # servo_min, servo_max = servo_max, servo_min
#print(F"Supplied min: {servo_min}, max: {servo_max}") #print(F"Supplied min: {servo_min}, max: {servo_max}")
if "picam" in self.plugins:
self.interface.attach_hook("picam", "pre_cam", self.led_on)
self.interface.attach_hook("picam", "post_cam", self.led_off)
self.interface.attach_hook("picam", "post_cam", self.run_servo)
elif "usbcam" in self.plugins:
self.interface.attach_hook("usbcam", "pre_cam", self.led_on) self.interface.attach_hook("usbcam", "pre_cam", self.led_on)
self.interface.attach_hook("usbcam", "post_cam", self.led_off) self.interface.attach_hook("usbcam", "post_cam", self.led_off)
self.interface.attach_hook("usbcam", "post_cam", self.run_servo) self.interface.attach_hook("usbcam", "post_cam", self.run_servo)
else:
raise ValueError("Need to either have picam or usbcam plugin loaded")
self.interface.register_function(self.test) self.interface.register_function(self.test)
def led_on(self): def led_on(self):
self.plugins["scout"].set_out1(True) self.plugins["scout"].set_out1(True)
#self.led_power.on() # self.led_power.on()
def led_off(self): def led_off(self):
self.plugins["scout"].set_out1(False) self.plugins["scout"].set_out1(False)
#self.led_power.off() # self.led_power.off()
def run_servo(self): def run_servo(self):
self.plugins["scout"].set_aux5v(True) self.plugins["scout"].set_aux5v(True)
#self.door_servo_power.on() # self.door_servo_power.on()
time.sleep(0.5) time.sleep(0.5)
self.plugins["scout"].set_pwm1(True, self.config["servo_open_pulse"]) self.plugins["scout"].set_pwm1(True, self.config["servo_open_pulse"])
@ -69,9 +71,9 @@ class MothtrapPlugin(shepherd.plugin.Plugin):
#self.door_servo.pulse_width = self.config["servo_closed_pulse"] / 1000000 #self.door_servo.pulse_width = self.config["servo_closed_pulse"] / 1000000
time.sleep(self.config["servo_open_time"]) time.sleep(self.config["servo_open_time"])
self.plugins["scout"].set_pwm1(False, self.config["servo_closed_pulse"]) self.plugins["scout"].set_pwm1(False, self.config["servo_closed_pulse"])
#self.door_servo.detach() # self.door_servo.detach()
self.plugins["scout"].set_aux5v(False) self.plugins["scout"].set_aux5v(False)
#self.door_servo_power.off() # self.door_servo_power.off()
def test(self): def test(self):
self.led_on() self.led_on()

@ -43,7 +43,7 @@ class PiCamPlugin(shepherd.plugin.Plugin):
confdef.add_def('jpeg_quality', shconf.IntDef(default=80, minval=60, maxval=95, optional=True, confdef.add_def('jpeg_quality', shconf.IntDef(default=80, minval=60, maxval=95, optional=True,
helptext="JPEG quality to save with. Max of 95, passed directly to Pillow")) helptext="JPEG quality to save with. Max of 95, passed directly to Pillow"))
array = confdef.add_def('trigger', shconf.TableArrayDef( array = confdef.add_def('trigger', shconf.DictListDef(
helptext="Array of triggers that will use all cameras")) helptext="Array of triggers that will use all cameras"))
array.add_def('hour', shconf.StringDef()) array.add_def('hour', shconf.StringDef())
array.add_def('minute', shconf.StringDef()) array.add_def('minute', shconf.StringDef())
@ -57,7 +57,7 @@ class PiCamPlugin(shepherd.plugin.Plugin):
self.hooks = pluginInterface.hooks self.hooks = pluginInterface.hooks
self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"]) self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"])
self.id = pluginInterface.coreconfig["id"] self.id = pluginInterface.coreconfig["name"]
self.interface.register_hook("pre_cam") self.interface.register_hook("pre_cam")
self.interface.register_hook("post_cam") self.interface.register_hook("post_cam")
@ -70,7 +70,7 @@ class PiCamPlugin(shepherd.plugin.Plugin):
# Seconds to wait for exposure and white balance auto-adjust to stabilise # Seconds to wait for exposure and white balance auto-adjust to stabilise
self.stabilise_delay = 3 self.stabilise_delay = 3
if self.config["save_directory"] is "": if self.config["save_directory"] == "":
self.save_directory = os.path.join(self.root_dir, "picamera") self.save_directory = os.path.join(self.root_dir, "picamera")
else: else:
self.save_directory = self.config["save_directory"] self.save_directory = self.config["save_directory"]
@ -130,11 +130,10 @@ class PiCamPlugin(shepherd.plugin.Plugin):
overlay.putalpha(128) overlay.putalpha(128)
return overlay return overlay
def camera_job(self): def camera_job(self):
self.hooks.pre_cam() self.hooks.pre_cam()
#Capture image # Capture image
print("Running camera...") print("Running camera...")
stream = io.BytesIO() stream = io.BytesIO()
with PiCamera() as picam: with PiCamera() as picam:
@ -146,7 +145,7 @@ class PiCamPlugin(shepherd.plugin.Plugin):
stream.seek(0) stream.seek(0)
img = Image.open(stream) img = Image.open(stream)
#Process image # Process image
image_time = datetime.now() image_time = datetime.now()
if self.config["show_overlay"]: if self.config["show_overlay"]:

@ -151,7 +151,7 @@ class Bucket():
(not item.endswith(".uploading")) and (not item.endswith(".uploading")) and
(not item.endswith(".uploaded"))): (not item.endswith(".uploaded"))):
bucket_files.append(item_path) bucket_files.append(item_path)
#TODO check for .uploaded files and either delete or # TODO check for .uploaded files and either delete or
# if keep_copy, move to self.old_path # if keep_copy, move to self.old_path
if bucket_files: if bucket_files:
@ -161,7 +161,7 @@ class Bucket():
class UploaderPlugin(shepherd.plugin.Plugin): class UploaderPlugin(shepherd.plugin.Plugin):
@staticmethod @staticmethod
def define_config(confdef): def define_config(confdef):
dests = confdef.add_def('destination', shconf.TableArrayDef()) dests = confdef.add_def('destination', shconf.DictListDef())
dests.add_def('name', shconf.StringDef()) dests.add_def('name', shconf.StringDef())
dests.add_def('protocol', shconf.StringDef()) dests.add_def('protocol', shconf.StringDef())
dests.add_def('address', shconf.StringDef(optional=True)) dests.add_def('address', shconf.StringDef(optional=True))
@ -174,7 +174,7 @@ class UploaderPlugin(shepherd.plugin.Plugin):
dests.add_def('add_id_to_path', shconf.BoolDef( dests.add_def('add_id_to_path', shconf.BoolDef(
default=True, optional=True)) default=True, optional=True))
buckets = confdef.add_def('bucket', shconf.TableArrayDef()) buckets = confdef.add_def('bucket', shconf.DictListDef())
buckets.add_def('name', shconf.StringDef()) buckets.add_def('name', shconf.StringDef())
buckets.add_def('open_link_on_new', shconf.BoolDef()) buckets.add_def('open_link_on_new', shconf.BoolDef())
buckets.add_def('opportunistic', shconf.BoolDef( buckets.add_def('opportunistic', shconf.BoolDef(
@ -190,7 +190,7 @@ class UploaderPlugin(shepherd.plugin.Plugin):
self.hooks = pluginInterface.hooks self.hooks = pluginInterface.hooks
self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"]) self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"])
self.id = pluginInterface.coreconfig["id"] self.id = pluginInterface.coreconfig["name"]
print("Uploader config:") print("Uploader config:")
print(self.config) print(self.config)

@ -29,11 +29,15 @@ CameraPort = namedtuple(
'CameraPort', ['usbPath', 'devicePath']) 'CameraPort', ['usbPath', 'devicePath'])
# Short wrapper to allow use in a ``with`` context # Short wrapper to allow use in a ``with`` context
class VideoCaptureCtx(): class VideoCaptureCtx():
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.capture_dev = cv2.VideoCapture(*args, **kwargs) self.capture_dev = cv2.VideoCapture(*args, **kwargs)
def __enter__(self): def __enter__(self):
return self.capture_dev return self.capture_dev
def __exit__(self, *args): def __exit__(self, *args):
self.capture_dev.release() self.capture_dev.release()
@ -116,13 +120,13 @@ class USBCamPlugin(shepherd.plugin.Plugin):
confdef.add_def('stabilise_delay', shconf.IntDef(default=5, minval=1, maxval=30, optional=True, confdef.add_def('stabilise_delay', shconf.IntDef(default=5, minval=1, maxval=30, optional=True,
helptext="Number of seconds to wait after starting each camera for exposure and white balance to settle")) helptext="Number of seconds to wait after starting each camera for exposure and white balance to settle"))
array = confdef.add_def('trigger', shconf.TableArrayDef( array = confdef.add_def('trigger', shconf.DictListDef(
helptext="Array of triggers that will use all cameras")) helptext="Array of triggers that will use all cameras"))
array.add_def('hour', shconf.StringDef()) array.add_def('hour', shconf.StringDef())
array.add_def('minute', shconf.StringDef()) array.add_def('minute', shconf.StringDef())
array.add_def('second', shconf.StringDef(default="0", optional=True)) array.add_def('second', shconf.StringDef(default="0", optional=True))
camarray = confdef.add_def('camera', shconf.TableArrayDef( camarray = confdef.add_def('camera', shconf.DictListDef(
helptext="List of cameras to try and connect to. Multiple ports may be listed, and any not connected will be skipped on each trigger.")) helptext="List of cameras to try and connect to. Multiple ports may be listed, and any not connected will be skipped on each trigger."))
camarray.add_def('name', shconf.StringDef(default="", optional=False, camarray.add_def('name', shconf.StringDef(default="", optional=False,
helptext="Name of camera, appended to filename and added to overlay")) helptext="Name of camera, appended to filename and added to overlay"))
@ -137,7 +141,7 @@ class USBCamPlugin(shepherd.plugin.Plugin):
self.hooks = pluginInterface.hooks self.hooks = pluginInterface.hooks
self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"]) self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"])
self.id = pluginInterface.coreconfig["id"] self.id = pluginInterface.coreconfig["name"]
self.interface.register_hook("pre_cam") self.interface.register_hook("pre_cam")
self.interface.register_hook("post_cam") self.interface.register_hook("post_cam")
@ -150,7 +154,7 @@ class USBCamPlugin(shepherd.plugin.Plugin):
self.gstlock = threading.Lock() self.gstlock = threading.Lock()
if self.config["save_directory"] is "": if self.config["save_directory"] == "":
self.save_directory = os.path.join(self.root_dir, "usbcamera") self.save_directory = os.path.join(self.root_dir, "usbcamera")
else: else:
self.save_directory = self.config["save_directory"] self.save_directory = self.config["save_directory"]
@ -237,7 +241,7 @@ class USBCamPlugin(shepherd.plugin.Plugin):
if self.config["append_id"]: if self.config["append_id"]:
image_filename = image_filename + " " + self.id image_filename = image_filename + " " + self.id
if camera_name is not "": if camera_name != "":
image_filename = image_filename+" "+camera_name image_filename = image_filename+" "+camera_name
image_filename = image_filename + ".jpg" image_filename = image_filename + ".jpg"
image_filename = os.path.join(self.save_directory, image_filename) image_filename = os.path.join(self.save_directory, image_filename)
@ -252,10 +256,10 @@ class USBCamPlugin(shepherd.plugin.Plugin):
with self.gstlock: with self.gstlock:
#gst_str = ('v4l2src device='+device_path+' ! ' # gst_str = ('v4l2src device='+device_path+' ! '
# 'videoconvert ! appsink drop=true max-buffers=1 sync=false') # 'videoconvert ! appsink drop=true max-buffers=1 sync=false')
#vidcap = cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER) # vidcap = cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER)
fmts = get_capture_formats(device_path) fmts = get_capture_formats(device_path)
@ -264,7 +268,6 @@ class USBCamPlugin(shepherd.plugin.Plugin):
size = get_largest_resolution(fmts["MJPG"]) size = get_largest_resolution(fmts["MJPG"])
set_camera_format_opencv(vidcap, "MJPG", size[0], size[1]) set_camera_format_opencv(vidcap, "MJPG", size[0], size[1])
# stream only starts after first grab # stream only starts after first grab
print("Starting cam") print("Starting cam")
@ -272,28 +275,27 @@ class USBCamPlugin(shepherd.plugin.Plugin):
delay_start = time.time() delay_start = time.time()
while (time.time() - delay_start) < self.config["stabilise_delay"]: while (time.time() - delay_start) < self.config["stabilise_delay"]:
vidcap.grab() vidcap.grab()
#time.sleep(self.config["stabilise_delay"]) # time.sleep(self.config["stabilise_delay"])
# clear old buffer # clear old buffer
#print("Flushing capture") # print("Flushing capture")
#vidcap.grab() # vidcap.grab()
print("Reading") print("Reading")
read_flag, frame = vidcap.read() read_flag, frame = vidcap.read()
#print("Changing to YUYV") # print("Changing to YUYV")
#if "YUYV" in fmts: # if "YUYV" in fmts:
# size = get_largest_resolution(fmts["YUYV"]) # size = get_largest_resolution(fmts["YUYV"])
# set_camera_format_opencv(vidcap, "YUYV", size[0], size[1]) # set_camera_format_opencv(vidcap, "YUYV", size[0], size[1])
#print("Reading again") # print("Reading again")
#read_flag, frame2 = vidcap.read() # read_flag, frame2 = vidcap.read()
if read_flag: if read_flag:
self._process_image(frame, camera_name) self._process_image(frame, camera_name)
#self._process_image(frame2, camera_name+"(2)") # self._process_image(frame2, camera_name+"(2)")
else: else:
print("Could not read camera "+camera_name + print("Could not read camera "+camera_name +
" on USB port "+device_path) " on USB port "+device_path)
def run_cameras(self, name_suffix = ""): def run_cameras(self, name_suffix=""):
connected_cams = OrderedDict(get_connected_cameras()) connected_cams = OrderedDict(get_connected_cameras())
for defined_name, defined_usb_path in self.defined_cams.items(): for defined_name, defined_usb_path in self.defined_cams.items():

@ -130,11 +130,11 @@ def save_jobs():
raise Exception("Could not save scheduler job " + raise Exception("Could not save scheduler job " +
job.id+" - Trigger is not a CronTrigger") job.id+" - Trigger is not a CronTrigger")
saved_jobs.append(job.id) saved_jobs.append(job.id)
if hasattr(job,"next_run_time"):
if next_job_time is not None: if next_job_time is not None:
if job.next_run_time < next_job_time: if job.next_run_time < next_job_time:
next_job_time = job.next_run_time next_job_time = job.next_run_time
else: else:
next_job_time = job.next_run_time next_job_time = job.next_run_time
with open(joblist_path+".writing", 'w+') as f: with open(joblist_path+".writing", 'w+') as f:
@ -189,8 +189,8 @@ def _jobs_changed(event):
print(retval) print(retval)
if retval == alarm_str: if retval == alarm_str:
if is_raspberry_pi(): if is_raspberry_pi():
print("Shutting down in 1 minute") print("Shutting down in 2 minutes")
time.sleep(60) time.sleep(120)
subprocess.run(["shutdown","now"]) subprocess.run(["shutdown","now"])
else: else:

@ -0,0 +1,38 @@
[shepherd]
hostname = "DPIRD-test"
id = "DPIRD-test"
plugin_dir = "/home/pi/plugins/"
plugins = ["scout", "picam", "uploader", "mothtrap"]
root_dir = "/home/pi/"
conf_edit_path = "/boot/shepherd.toml"
control_server = "api.shepherd.distreon.net"
api_key = "v2EgvYzx79c8fCP4P7jlWxTZ3pc"
[scout]
boardver = "3"
serialport = "/dev/ttyS0"
[uploader]
[[uploader.destination]]
name = "agricSFTP"
protocol = "sftp"
address = "agric.files.distreon.net"
port = 2222
path = "/mothtraps"
username = "agric"
password = "asherhaze"
[[uploader.bucket]]
name = "imageupload"
open_link_on_new = true
keep_copy = false
destination = "agricSFTP"
[picam]
upload_images = true
upload_bucket = "imageupload"
[[picam.trigger]]
hour = "*"
minute ="*/15"
second = "0"
[mothtrap]
servo_open_pulse = 900
servo_closed_pulse = 2100
servo_open_time = 3
# shepherd_message: Successfully applied this config at:2020-03-29 18:29:28.566836

@ -0,0 +1,50 @@
[shepherd]
hostname = "DPIRD-test"
id = "DPIRD-test"
plugin_dir = "/home/pi/plugins/"
plugins = ["scout", "usbcam", "uploader", "flytrap"]
root_dir = "/home/pi/"
conf_edit_path = "/boot/shepherd.toml"
control_server = "api.shepherd.distreon.net"
api_key = "v2EgvYzx79c8fCP4P7jlWxTZ3pc"
[scout]
boardver = "3"
serialport = "/dev/ttyS0"
[uploader]
[[uploader.destination]]
name = "agricSFTP"
protocol = "sftp"
address = "agric.files.distreon.net"
port = 2222
path = "/mothtraps"
username = "agric"
password = "asherhaze"
[[uploader.bucket]]
name = "imageupload"
open_link_on_new = true
keep_copy = false
destination = "agricSFTP"
[usbcam]
upload_images = true
upload_bucket = "imageupload"
[[usbcam.camera]]
name = "USB1"
usb_port = "1.2"
[[usbcam.camera]]
name = "USB2"
usb_port = "1.3"
[[usbcam.camera]]
name = "USB3"
usb_port = "1.1"
[[usbcam.camera]]
name = "USB"
usb_port = "*"
[[usbcam.trigger]]
hour = "*"
minute ="0"
second = "0"
[flytrap]
servo_open_pulse = 2100
servo_closed_pulse = 900
servo_open_time = 3
# shepherd_message: Successfully applied this config at:2019-12-16 00:59:30.985447
Loading…
Cancel
Save