Пример #1
0
def check_for_remigration(to_do_list):
    """
    Make sure we're not queueing up a device we've already migrated
    """
    tbapi_old = TbApi(birdhouse_utils.make_mothership_url(old_server_ip),
                      thingsboard_username, thingsboard_password)
    tbapi_new = TbApi(birdhouse_utils.make_mothership_url(new_server_ip),
                      thingsboard_username, thingsboard_password)

    old_client = create_client(old_server_ip)
    new_client = create_client(new_server_ip)

    print(
        "Conducting remigration checks (to make sure device hasn't already been migrated to new server)"
    )

    for num in to_do_list:
        print(".", end="")
        name = birdhouse_utils.make_device_name(num)

        if not device_has_data(tbapi_old, old_client, name):
            print(
                f"\nThere is no data on the old server for device {name}.  Nothing to migrate."
            )
            exit()

        if device_has_been_migrated(tbapi_old, old_client, tbapi_new,
                                    new_client, name):
            print(f"\nDevice {name} has already been migrated.")
            exit()
    print()
Пример #2
0
def main():
    tbapi = TbApi(motherShipUrl, username, password)

    # Lookup missing fields, such as zip, lat, and lon
    birdhouse_utils.update_customer_data(cust_info)

    if cust_info["lat"] is None or cust_info["lon"] is None:
        print("Must have valid lat/lon to continue!")
        exit(1)

    name = birdhouse_utils.make_device_name(birdhouse_number)

    cust = tbapi.get_customer(name)
    devices = tbapi.get_customer_devices(cust)

    print(devices)

    device = tbapi.get_device_by_name(name)

    customer = tbapi.update_customer(cust, None, cust_info["address"],
                                     cust_info["address2"], cust_info["city"],
                                     cust_info["state"], cust_info["zip"],
                                     cust_info["country"])
    server_attributes = {
        "latitude": cust_info["lat"],
        "longitude": cust_info["lon"],
        "address": birdhouse_utils.one_line_address(cust_info)
    }
    tbapi.set_server_attributes(device, server_attributes)

    exit()

    cust = tbapi.get_customer(name)
Пример #3
0
def ensure_devices_exist(device_nums):
    """
    Ensure all devices we're going to process exist on both the source and destination machines
    """
    tbapi_old = TbApi(birdhouse_utils.make_mothership_url(old_server_ip),
                      thingsboard_username, thingsboard_password)
    tbapi_new = TbApi(birdhouse_utils.make_mothership_url(new_server_ip),
                      thingsboard_username, thingsboard_password)

    print(
        "Making sure every device we want to migrate exists on both source and desitnation machines"
    )

    for num in device_nums:
        print(".", end="")

        name = birdhouse_utils.make_device_name(num)

        old_device = tbapi_old.get_device_by_name(name)
        if old_device is None:
            print(f"\nDevice {name} does not exist on old server!")
            exit()

        new_device = tbapi_new.get_device_by_name(name)
        if new_device is None:
            print(f"\nDevice {name} does not exist on new server!")
            exit()

        old_key = tbapi_old.get_id(old_device)
        new_key = tbapi_new.get_id(new_device)

        if old_key != new_key:
            print("\nDevice keys are different on old and new servers!")
            exit()
    print()
Пример #4
0
def main():

    mothership_url = birdhouse_utils.make_mothership_url(args, config)
    tbapi = TbApi(mothership_url, thingsboard_username, thingsboard_password)

    for num in args["<num>"]:
        print(f"Retrieving details for device {num}... ", end='', flush=True)
        name = birdhouse_utils.make_device_name(num)
        device = tbapi.get_device_by_name(name)

        if device is None:
            print(f"Failed.\nCould not find device {num}... Aborting.")
            exit()

        token = tbapi.get_device_token(device)
        print("done.")
        print(token)
Пример #5
0
def make_params(nums):
    mothership_url = birdhouse_utils.make_mothership_url(args)

    tbapi = TbApi(mothership_url, thingsboard_username, thingsboard_password)

    params = []

    for num in nums:
        print(f"Retrieving details for device {num}... ", end='', flush=True)
        device_name = birdhouse_utils.make_device_name(num)
        dash_name = birdhouse_utils.make_dash_name(num)

        device = tbapi.get_device_by_name(device_name)
        dash = tbapi.get_dashboard_by_name(dash_name)
        dash_url = tbapi.get_public_dash_url(dash)
        tiny_url = make_tiny_url(dash_url)

        if device is None:
            print(f"Failed.\nCould not find device {num}... Aborting.")
            exit()

        token = tbapi.get_device_token(device)

        params.append((
            birdhouse_utils.get_sensor_type(num)[1],
            birdhouse_utils.make_device_number(num),
            token,
            tiny_url
        ))
        print("done.")

    return params
Пример #6
0
def find_unmigrated_devices(old_ip, new_ip):
    tbapi_old = TbApi(birdhouse_utils.make_mothership_url(old_ip),
                      thingsboard_username, thingsboard_password)
    tbapi_new = TbApi(birdhouse_utils.make_mothership_url(new_ip),
                      thingsboard_username, thingsboard_password)

    old_client = create_client(old_ip)
    new_client = create_client(new_ip)

    devices_on_old = tbapi_old.get_all_devices()
    devices_on_new = tbapi_new.get_all_devices()

    unmigrated_ready_to_go, migrated, unmigrated, no_data, no_data_2, new_only = list(
    ), list(), list(), list(), list(), list()

    for dev in devices_on_old:
        name = dev["name"]

        print(f"Device {name}")
        has_telem_on_old = has_telemetry(tbapi_old, dev)
        has_telem_on_new = has_telemetry(tbapi_new, dev)

        if not device_has_data(tbapi_old, old_client, name):
            no_data_2.append(name)

        if has_telem_on_old:
            if has_telem_on_new:
                # Telemetry exists on both servers; has it been migrated, or merely switched itself over?
                if device_has_been_migrated(tbapi_old, old_client, tbapi_new,
                                            new_client, name):
                    migrated.append(name)
                else:
                    unmigrated_ready_to_go.append(name)
            else:  # on old, not on new
                unmigrated.append(name)
        else:  # not old
            if has_telem_on_new:
                new_only.append(name)
            else:
                no_data.append(name)

    for dev in devices_on_new:
        if dev not in devices_on_old:
            new_only.append(dev["name"])

    print(f"Migrated {sorted(migrated)}")
    print(
        f"Unmigrated and unswitched (possibly no longer collecting data): {sorted(unmigrated)}"
    )
    print(f"Ready to migrate: {sorted(unmigrated_ready_to_go)}")
    # Not sure which of these is more reliable -- they generate their results using different methods
    print(f"No data: {sorted(no_data)}")
    print(f"No data2: {sorted(no_data_2)}")
    print(f"New only, nothing to do: {sorted(new_only)}")

    exit()
Пример #7
0
def main():
    
    global args, tbapi, port


    tbapi = TbApi(motherShipUrl, config.thingsboard_username, config.thingsboard_password)


    parser = argparse.ArgumentParser(description='Configurate your birdhouse!')

    parser.add_argument('--number', '-n', metavar='NNN', type=str, help='the number of your birdhouse')
    parser.add_argument('--localssid', metavar='ssid', type=str, help='The local SSID for the birdhouse wifi')
    parser.add_argument('--localpass', metavar='pass', type=str, help='The local password for the birdhouse wifi')
    parser.add_argument('--wifissid', metavar='ssid', type=str, help='The SSID for the local wifi')
    parser.add_argument('--wifipass', metavar='pass', type=str, help='The password for the local wifi')
    parser.add_argument('--mqtturl', metavar='url', type=str, help='The url for sending telemetry to')
    parser.add_argument('--mqttport', metavar='port', type=str, help='The server\'s MQTT port')


    parser.add_argument('--nocompile', action='store_true', help="skip compilation, upload stored binary")
    parser.add_argument('--noupload', action='store_true', help="skip compilation and upload, rely on previously uploaded binary")

    args = parser.parse_args()
    
    # Find out what port the Birdhouse is on:
    try:
        port = get_best_guess_port()

        if not port:
            print("Plug birdhouse in, please!")
            port = polling.poll(lambda: get_best_guess_port(), timeout=30, step=0.5)
    except Exception as ex:
        print("Could not find any COM ports")
        raise ex


    # compile_and_upload_firmware(compile=(not args.nocompile), upload=(not args.noupload))

    # Validate
    if args.number is not None:
        if len(args.number) != 3:
            print("Birdhouse number must be 3 digits (include leading 0s)")
            sys.exit(1)
    # else we'll try to get it from the birdhouse itself
    # sys.exit()


    runUi()
Пример #8
0
#!/usr/bin/env python
import json
import web  # sudo pip3 install git+https://github.com/webpy/webpy#egg=web.py
import googlemaps  # sudo pip install googlemaps
import geopy.distance  # sudo pip install geopy
import re
import os
import base64

# pip install git+git://github.com/eykamp/thingsboard_api_tools.git --upgrade
# sudo pip install git+git://github.com/eykamp/thingsboard_api_tools.git --upgrade
from thingsboard_api_tools import TbApi

from redlight_greenlight_config import motherShipUrl, username, password, data_encoding, google_geolocation_key

tbapi = TbApi(motherShipUrl, username, password)
gmaps = googlemaps.Client(key=google_geolocation_key)

urls = ('/', 'set_led_color', '/hotspots/', 'handle_hotspots', '/update/',
        'handle_update')

app = web.application(urls, globals())


class handle_hotspots:
    def POST(self):
        try:
            data = web.data()
            decoded = data.decode(data_encoding)
            incoming_data = json.loads(decoded)
            # print(incoming_data)
Пример #9
0
        CFG = toml.load(configpath)
    except FileNotFoundError:
        show_config_help(configpath)
        print("Using defaults...")
        CFG = dict(motherShipUrl="FIXME",
                   username="******",
                   password="******",
                   data_encoding="utf-8",
                   google_geolocation_key="FIXME",
                   firmware_images_folder="FIXME")
        print(CFG)
    return CFG


CFG = load_config(build_config_path())
tbapi = TbApi(CFG['motherShipUrl'], CFG['username'], CFG['password'])
app = Flask(__name__)


def get_immediate_subdirectories(a_dir):
    return [
        name for name in os.listdir(a_dir)
        if os.path.isdir(os.path.join(a_dir, name))
    ]


def get_geolocate():
    # helper function to assist with testability, so it can be mocked
    return googlemaps.Client(key=CFG['google_geolocation_key']).geolocate

Пример #10
0
def main():
    cleanup = True

    tbapi = TbApi(motherShipUrl, username, password)

    # Get a definition of our template dashboard
    template_dash = tbapi.get_dashboard_by_name(dashboard_template_name)
    dash_def = tbapi.get_dashboard_definition(tbapi.get_id(template_dash))

    # Lookup missing fields, such as zip, lat, and lon
    update_customer_data()

    if cust_lat is None or cust_lon is None:
        print("Must have valid lat/lon in order to add device!")
        exit(1)

    # Create new customer and device records on the server
    customer = tbapi.add_customer(cust_name, cust_address, cust_address2,
                                  cust_city, cust_state, cust_zip,
                                  cust_country, cust_email, cust_phone)

    server_attributes = {"latitude": cust_lat, "longitude": cust_lon}

    shared_attributes = {"LED": "Unknown", "nonce": 0}
    device = tbapi.add_device(make_device_name(cust_name), sensor_type,
                              shared_attributes, server_attributes)
    device_id = tbapi.get_id(device)

    # We need to store the device token as a server attribute so our REST services can get access to it
    device_token = tbapi.get_device_token(device_id)

    server_attributes = {"device_token": device_token}

    tbapi.set_server_attributes(device_id, server_attributes)

    # Upate the dash def. to point at the device we just created (modifies dash_def)
    update_dash_def(dash_def, cust_name, device_id)

    # Create a new dash with our definition, and assign it to the new customer
    dash = tbapi.create_dashboard_for_customer(cust_name + ' Dash', dash_def)
    tbapi.assign_dash_to_user(tbapi.get_id(dash), tbapi.get_id(customer))

    if cleanup:
        # input("Press Enter to continue...")   # Don't run from Sublime with this line enabled!!!

        print("Cleaning up!")
        tbapi.delete_dashboard(tbapi.get_id(dash))
        tbapi.delete_device(device_id)
        tbapi.delete_customer_by_id(tbapi.get_id(customer))
Пример #11
0
from thingsboard_api_tools import TbApi  # pip install git+git://github.com/eykamp/thingsboard_api_tools.git --upgrade
from config import thingsboard_username, thingsboard_password  # You'll need to create this... Be sure to gitignore it!
import config

args = docopt(__doc__)

winscp_profile = args['<winscpprofile>']
devices = args['<devices>'] if not args['all'] else "all"
clean = args['--clean']
build_only = args['build']

# clean = True
# build_only = False

mothership_url = birdhouse_utils.make_mothership_url(args, config)
tbapi = TbApi(mothership_url, thingsboard_username, thingsboard_password)

winscp_program_location = r"c:\Program Files (x86)\WinSCP\WinSCP.com"
arduino_build_exe_location = r"c:\Program Files (x86)\Arduino\arduino_debug.exe"

source_name = "firmware"
source_file = source_name + ".ino"
build_folder = r"C:\Temp\BirdhouseFirmwareBuildFolder"  # Where we store the firmware image we're building
remote_dir = "/sensorbot/firmware_images"  # Where we store the firmware images on the update server


def main():
    version = extract_version(source_file)
    build_target_file = source_name + "_" + str(version) + ".bin"

    # Important: Use the .com version here, not the .exe
Пример #12
0
def main(settings):
    print("Sensorbot Device Provisioning Script Version " + __version__)

    if upload_img or should_upload_firmware:
        settings.esp = find_birdhouse_port()
        if settings.esp is None:
            if ui_mode:
                start_ui_no_device()
            else:
                exit()

    if upload_img:
        if not os.path.isfile(firmware_image):
            print(f"Could not find firmware image {firmware_image}")
            print("Aborting.")
            exit()

        upload_firmware(print, settings.esp, firmware_image)
        exit()

    validate_led_style(settings.led_style)

    # Instantiate our API helper if needed
    if should_set_up_thingsboard:
        tbapi = TbApi(mothership_url, thingsboard_username,
                      thingsboard_password)

    if should_delete_only:
        birdhouse_utils.purge_server_objects_for_device(
            tbapi, settings.birdhouse_number)
        exit()

    device_name = birdhouse_utils.make_device_name(settings.birdhouse_number)
    if settings.birdhouse_number is not None:
        print("Configuring device '" + device_name + "'\n")

    # Get the port first to ensure our local house is in order before we validate things over the network
    validated_token = False
    if should_upload_firmware:
        if settings.birdhouse_number is not None and settings.device_token is not None:
            if not validate_device_token(settings.birdhouse_number,
                                         settings.device_token):
                print(
                    "Passed an invalid device token for the specified device.")
                print("Aborting.")
                exit()
            validated_token = True

    if should_create_thingsboard_objects:
        settings.device_token = create_server_objects(
            tbapi, settings.birdhouse_number
        )  # This will fail if server objects already exist

    if testmode:
        input("Press Enter to cleanup created objects...")
        settings.birdhouse_utils.purge_server_objects_for_device(
            tbapi, settings.birdhouse_number)
        exit()

    # assign_device_to_public_user(token, device_id)

    if ui_mode:
        start_ui(tbapi, settings.esp._port)
        exit()

    if not validated_token:
        settings.device_token = get_or_validate_device_token(
            tbapi, settings.birdhouse_number, settings.device_token,
            should_create_thingsboard_objects)

    if should_upload_firmware:
        upload_firmware_and_configure(print, settings)

    if attributes_only:
        set_params(print, settings)
Пример #13
0
def main():

    mothership_url = birdhouse_utils.make_mothership_url(args, config)
    tbapi = TbApi(mothership_url, thingsboard_username, thingsboard_password)

    print(f"Retrieving template dashboard {template_dash}... ",
          end='',
          flush=True)
    template_dash_def = tbapi.get_dashboard_definition(
        tbapi.get_dashboard_by_name(template_dash))

    # We also need the id of the device being swapped out
    template_device_id = tbapi.get_id(
        tbapi.get_device_by_name(
            birdhouse_utils.make_device_name(args["<device>"])))

    print(" done.")

    all_devices = tbapi.get_devices_by_name(copy_to_pattern)

    for device in all_devices:
        num = birdhouse_utils.get_device_number_from_name(device["name"])

        print(f"Updating dashboard for {device['name']}")
        dash_name_being_replaced = birdhouse_utils.make_dash_name(num)
        device_name = birdhouse_utils.make_device_name(num)
        device = tbapi.get_device_by_name(device_name)
        device_id = tbapi.get_id(device)

        # The dash we are replacing:
        dash_being_replaced = tbapi.get_dashboard_by_name(
            dash_name_being_replaced)
        dash_id_being_replaced = tbapi.get_id(dash_being_replaced)

        dash_def = tbapi.get_dashboard_definition(
            tbapi.get_dashboard_by_name(
                template_dash))  # dash_def will be modified
        birdhouse_utils.reassign_dash_to_new_device(dash_def,
                                                    dash_name_being_replaced,
                                                    template_device_id,
                                                    device_id, device_name)

        dash_def["id"]["id"] = dash_id_being_replaced

        # del_humidity(dash_def)
        # exit()

        tbapi.save_dashboard(dash_def)
Пример #14
0
# Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

import re
import datetime, time, pytz
import logging
import deq_tools                                                    # pip install deq_tools

from thingsboard_api_tools import TbApi                             # pip install git+git://github.com/eykamp/thingsboard_api_tools.git --upgrade
from config import motherShipUrl, username, password, deq_logfile   # You'll need to create this... Be sure to gitignore it!

tbapi = TbApi(motherShipUrl, username, password)

device_name = 'DEQ (SEL)'
deq_tz_name = 'US/Pacific'

logging.basicConfig(filename=deq_logfile, format='%(asctime)s %(message)s', level=logging.INFO)    # WARN, INFO, DEBUG


# Data is stored as if it were coming from one of our devices
device = tbapi.get_device_by_name(device_name)
device_token = tbapi.get_device_token(tbapi.get_id(device))


# This is the earliest timestamp we're interested in.  The first time we run this script, all data since this date will be imported. 
# Making the date unnecessarily early will make this script run very slowly.
earliest_ts = "2018/04/28T00:00"        # DEQ uses ISO datetime format: YYYY/MM/DDTHH:MM
Пример #15
0
def verify_devices_remapped(device_nums,
                            min_interval=120,
                            age_considered_offline=7 * DAYS):  # In seconds
    """
    Look at the ages of the most recent telemetry, and ensure each device is sending current telemetry to the new server.
    The theory is that once a device is talking to the new server, it will never go back to the old, and we can safely
    shift all telemetry from the old server.

    min_interval is the minimum time, in seconds, that the new server must be ahead of the old server for this check to pass.

    Note that if the most recent telemetry on the old server is older than age_considered_offline, we'll assume the device is out of contact
    (perhaps disconnceted or off), and we'll go ahead and migrate the data over.
    """
    tbapi_old = TbApi(birdhouse_utils.make_mothership_url(old_server_ip),
                      thingsboard_username, thingsboard_password)
    tbapi_new = TbApi(birdhouse_utils.make_mothership_url(new_server_ip),
                      thingsboard_username, thingsboard_password)

    old_client = create_client(old_server_ip)
    new_client = create_client(new_server_ip)

    print(
        "Verifying devices have attached themselves to the new server and aren't still sending data to the old"
    )

    now = int(time.time() * 1000)

    for num in device_nums:
        print(".", end="")

        name = birdhouse_utils.make_device_name(num)
        latest_old = get_latest_telemetry_date(tbapi_old, old_client,
                                               name) or 0

        if latest_old == 0:  # There is no data on the old server; no need to migrate, but no problem moving forward, either
            continue

        latest_new = get_latest_telemetry_date(tbapi_new, new_client,
                                               name) or 0

        age_of_old = int(
            (now - latest_old) /
            1000)  # Age of most recent telemetry on old server in seconds

        diff = int(
            (latest_new - latest_old) / 1000
        )  # Diffrence in ages between most recent telmetry on new and old server, in seconds

        if age_of_old < age_considered_offline and diff < min_interval:
            print(
                f"\nIt looks like device {name} is still active and hasn't switched to new server yet.  Not ready to migrate data!"
            )
            print(
                f"\tLast telemetry on old server was {format_time_delta(age_of_old)} ago."
            )
            if latest_new == 0:
                print(
                    "\tThe device has not yet sent any data to the new server."
                )
            else:
                print(
                    f"\tLast telemetry on new server was {format_time_delta(now - latest_new)} ago."
                )
            exit()
    print()