def set_hardware_info(hardware_version: str, gb_reader_count: str): """Set the hardware info into the HardwareDefinition table. :param hardware_version: The hardware revision. :type hardware_version: str :param gb_reader_count: The number of 1Wire readerchips the FarmDevice has. :type gb_reader_count: str """ logger.debug( f"setting version: {hardware_version} grainbin_reader: {gb_reader_count}" ) session = get_session() device_name = get_device_name() serial_number = get_serial() try: hd = session.query(Hardware).one() except NoResultFound: hd = Hardware() session.add(hd) hd.hardware_version = hardware_version hd.device_name = device_name hd.serial_number = serial_number hd.grainbin_reader_count = int(gb_reader_count) session.commit() session.close()
def get_external_interface() -> str: """Get the external interface. This is the interface that is used to send traffic out for any AP. First check if eth0 is present. Then check if there is a wlan interface that has a state of 'dhcp' :return: The name of the interface that is for external traffic, or 'None' :rtype: str """ session = get_session() if ethernet_connected(): ethernet = session.query(Interface).filter_by(interface="eth0").first() ethernet.is_external = True session.commit() session.close() return "eth0" # now check if it is either wlan0 or wlan1 interfaces = session.query(Interface).filter_by(state="dhcp").all() for interface in interfaces: if interface.interface != "eth0": interface.is_external = True session.commit() session.close() return str(interface.interface) session.close() return "None"
def get_grainbin_updates(session: Session = None) -> list: """Get all grainbin updates as a list for each grainbin.""" close_session = False if not session: close_session = True session = get_session() all_updates: list = [] grainbins: list[Grainbin] = session.query(Grainbin).all() all_busses = get_all_busses() for grainbin in grainbins: if grainbin.bus_number_string in all_busses: update = get_indivudual_grainbin_update(grainbin) all_updates.append(update) else: LOGGER.warning( f"Bus {grainbin.bus_number_string} not currently connected when trying to create update." ) session.commit() if close_session: session.close() return all_updates
def update(self, session=None, commit=True, **kwargs): """Update specific fields of a record.""" if session is None: session = get_session() for attr, value in kwargs.items(): setattr(self, attr, value) return self.save(session) if commit else self
def get_device_info(session=None) -> dict: """Return a device information dictionary.""" close_session = False if not session: close_session = True session = get_session() device: Device = session.query(Device).first() device.interior_temp = temperature(device.interior_sensor) device.exterior_temp = temperature(device.exterior_sensor) session.commit() info: dict = {} info["created_at"] = datetime.datetime.now() info["id"] = device.device_id device_info = {} device_info["device_id"] = device.device_id device_info["hardware_version"] = device.hardware_version device_info["software_version"] = device.software_version device_info["interior_temp"] = device.interior_temp device_info["exterior_temp"] = device.exterior_temp device_info["grainbin_count"] = device.grainbin_count device_info["last_updated"] = device.last_updated info["data"] = device_info if close_session: session.close() return info
def main(): """The main loop of the application.""" config = get_config() logger = configure_logging(config) session = get_session() if not get_rabbitmq_address(logger, session): logger.error("No address for rabbitmq server found") time.sleep(1) return # device_connection = Process(target=run_connection) scheduler_process = Process(target=run_scheduled_tasks) # device_connection.start() scheduler_process.start() try: # device_connection.join() scheduler_process.join() except KeyboardInterrupt: logger.warning("Keyboard interrupt in main process") time.sleep(1) # device_connection.terminate() # device_connection.join() scheduler_process.terminate() scheduler_process.join() return
def set_wpa_mode(): """Perform the setup and intialization work for interfaces with no ap present.""" logger.debug("setting all wlan into wpa mode") session = get_session() # get the info for the wpa_supplicant file wifi_defs = session.query(Wifi).filter(Wifi.mode != "ap").all() networks = [] for wifi in wifi_defs: new_network = {} new_network["ssid"] = wifi.name new_network["password"] = wifi.password networks.append(new_network) iptables_file(None, None, flush_only=True) interface_file() wpa_supplicant_file(networks) dhcpcd_file() config = get_config() path = config.APP_DIR + "/network/wpa_script.sh" command = ["sudo", "sh", path] subprocess.check_call(command) session.close()
def set_interfaces(interfaces: List): """Set interface information into database and configure hardware accordingly. Args: interfaces (List): A list of dictionaries with the required information. """ session = get_session() wifi_ap_present = False for interface in interfaces: try: db_result = (session.query(Interface).filter_by( interface=interface["name"]).one()) except NoResultFound: db_result = Interface(interface["name"]) session.add(db_result) db_result.is_active = True db_result.is_for_fm = interface["is_for_fm"] db_result.state = interface["state"] if interface["state"] == "ap": wifi_ap_present = True if "creds" in interface: add_wifi_network( wifi_name=interface["creds"]["ssid"], wifi_password=interface["creds"]["password"], interface=db_result, ) session.commit() if wifi_ap_present: set_ap_mode() else: set_wpa_mode()
def save(self, session=None, commit=True): """Save the record.""" if session is None: session = get_session() session.add(self) if commit: session.commit() return self
def wifi_info() -> List: """Get a list of WiFi details for all wlan interfaces. Returns: List: For each interface, a dictionary of details is added to the list Keys of the dictionary are: interface: the interface if ap: clients: the number of clients currently connected ssid: the ssid of the ap password: the password of the ap if dhcp: state: either the SSID currently connected to or False state_boolean: boolean value for state. True or False if state: address: the IPV4 address ssid: the ssid of the dhcp interface password: the password of the dhcp interface """ logger.debug("getting wifi information") wlan_interfaces = get_interfaces(keep_eth=False) wifi = [] session = get_session() for w_interface in wlan_interfaces: try: info = {} interface = session.query(Interface).filter_by( interface=w_interface).one() info["interface"] = interface if interface.state == "ap": info["clients"] = wifi_ap_clients(interface.interface) info["ssid"] = interface.credentials[0].name info["password"] = interface.credentials[0].password else: info["state"] = wifi_dhcp_info(interface.interface) if info["state"] is False: info["state_boolean"] = False else: info["state_boolean"] = True if w_interface in netifaces.interfaces(): address = netifaces.ifaddresses(w_interface) info["address"] = address[netifaces.AF_INET][0]["addr"] if interface.credentials: info["ssid"] = interface.credentials[0].name info["password"] = interface.credentials[0].password wifi.append(info) except NoResultFound: pass session.close() return wifi
def __init__(self, logger): """Overwrite the Connection __init__.""" super().__init__(logger) # pylint: disable=invalid-name self.HEARTBEAT_MESSGES = None self.SERVER_MESSAGES = None self._session = get_session() self._host = self._session.query(db_Connection.address).scalar()
def set_ap_mode(): """Perform the setup and intialization work for interfaces with an ap present.""" logger.debug("setting wifi into ap mode") session = get_session() # get the wlan0 and wlan1 dhcp states try: ap_interface = session.query(Interface).filter_by(state="ap").first() ap_ssid = ap_interface.credentials[0].name ap_password = ap_interface.credentials[0].password except NoResultFound: # error. abort logger.warning("No interface with state set to 'ap'. Aborting") return # get info for interface file if ap_interface.interface == "wlan0": wlan0_dhcp = False wlan1_dhcp = True else: wlan0_dhcp = True wlan1_dhcp = False # get the info for the wpa_supplicant file wifi_defs = session.query(Wifi).filter(Wifi.mode != "ap").all() networks = [] for wifi in wifi_defs: new_network = {} new_network["ssid"] = wifi.name new_network["password"] = wifi.password networks.append(new_network) # get the information for the iptables_file internal_interface = ap_interface.interface external_interface = get_external_interface() iptables_file(external_interface, internal_interface) interface_file(wlan0_dhcp=wlan0_dhcp, wlan1_dhcp=wlan1_dhcp) wpa_supplicant_file(networks) dhcpcd_file(interface=ap_interface.interface) dnsmasq_file(interface=ap_interface.interface) hostapd_file(ap_interface.interface, ap_ssid, ap_password) config = get_config() path = config.APP_DIR + "/network/ap_script.sh" command = ["sudo", "sh", path, ap_interface.interface] subprocess.check_call(command) session.close()
def delete_all_data(confirm): """Delete all data from the database.""" if not confirm: click.echo( "Action was not confirmed (command option '--confirm'). No change made." ) else: click.echo("deleting all data from the database.") base = get_base() session = get_session() for table in reversed(base.metadata.sorted_tables): session.execute(table.delete()) session.commit() click.echo("done")
def initialize_device(): """Set up the Device info into the database. By this time, the Hardware and Software entries must be added to the database. """ session = get_session() try: hd = session.query(Hardware).one() sd = session.query(Software).one() except NoResultFound: session.close() return try: device = session.query(Device).one() except NoResultFound: device = Device( device_id=hd.serial_number, interior_sensor=hd.interior_sensor, exterior_sensor=hd.exterior_sensor, ) session.add(device) device.hardware_version = hd.hardware_version device.software_version = sd.software_version device.interior_sensor = hd.interior_sensor device.exterior_sensor = hd.exterior_sensor # check if grainbins already exisit (running setup again) # and remove them if they are present if len(device.grainbins) > 0: for grainbin in device.grainbins: session.delete(grainbin) device.grainbin_count = 0 session.commit() # set grainbin info grainbins = initialize_grainbin(device.device_id, hd.grainbin_reader_count) for grainbin in grainbins: device.grainbins.append(grainbin) device.grainbin_count = len(grainbins) session.commit() session.close() return
def delete_wifi_network(wifi_id: str) -> bool: """Delete a WiFi network. Args: wifi_id (str): The ID of the WiFi netowrk to delete Returns: bool: True if an entry was deleted. False if nothing was deleted. """ session = get_session() deleted_count = session.query(Wifi).filter_by(id=wifi_id).delete() session.commit() session.close() return bool(deleted_count > 0)
def set_sensor_info(interior: int, exterior: int): """Set the sensor details for the device. There should be two 1W sensors connected directly to the device. This gets the sensors and sets which one is interior and exterior into the Hardware table. input interior should be '1' or '2' and specifies which of the two sensors is the interior one. """ logger.debug("setting sensor info for device") # subtract 1 from the passed in values for interior and exterior to offset 0 index interior = int(interior) - 1 exterior = int(exterior) - 1 # get the 1W sensors that are connected directly to the device # these are the interior and exterior temp sensors sensors = get_connected_sensors() int_sensor = "no_sensor_selected" ext_sensor = "no_sensor_selected" try: int_sensor = sensors[interior]["name"] except IndexError: pass try: ext_sensor = sensors[exterior]["name"] except IndexError: pass logger.debug(f"interior sensor is: {int_sensor}") logger.debug(f"exterior sensor is: {ext_sensor}") # now set the sensor info into the tables session = get_session() try: hd = session.query(Hardware).one() except NoResultFound: hd = Hardware() session.add(hd) hd.interior_sensor = int_sensor hd.exterior_sensor = ext_sensor session.commit() session.close()
def scan_wifi(interface=None) -> List: """Scan the interface for the available wifi networks. Args: interface (str, optional): the interface to search on. Defaults to None. if no interface is given, try an interface from the database that is 'dhcp' Returns: List: A list of strings that are the found networks """ # if no interface is given, try find an interface in the database # that has the state set to 'dhcp' and is not 'eth' if interface is None: session = get_session() interfaces = session.query(Interface).all() for x in interfaces: if not x.interface.startswith("eth"): if x.state == "dhcp": interface = x.interface session.close() # exit if still no interface if interface is None: logger.warning("No interface available to scan wifi networks") return [] # scan the interface for networks command = ["sudo", "iwlist", interface, "scan"] output = subprocess.check_output(command, universal_newlines=True) index = output.find('ESSID:"') ssid = [] while index > 0: stop = output.find('"\n', index) ssid.append(output[index + 7:stop]) output = output[stop + 2:] index = output.find('ESSID:"') return ssid
def add_wifi_network(wifi_name: str, wifi_password: str, interface: Interface = None) -> Optional[Wifi]: """Add a wifi entry to the database of stored WiFi networks. Args: wifi_name (str): The SSID of the WiFi network. wifi_password (str): The password of the WiFi network. interface (Interface, optional): The Interface to assign the WiFi to. If Noine, the first 'wlan' interface set to DHCP is used. Defaults to None. Returns: Optional[Wifi]: The WiFi instance that was created or None if no Interface is found. """ # if no interface is passed in, create a session and look for a valid interface if interface is None: session = get_session() interfaces = session.query(Interface).all() for x in interfaces: # find first available wlan interface that is not dhcp if x.interface != "eth0" and x.state == "dhcp": interface = x break # if an interface is passed in, get the session from the interface. else: session = object_session(interface) if interface is None: logger.error("No interface available to add new wifi network") return None # have an interface. now create a Wifi entry new_wifi = Wifi() new_wifi.name = wifi_name new_wifi.password = wifi_password new_wifi.mode = "dhcp" new_wifi.interface = interface new_wifi.save(session) return new_wifi
def set_software_info(software_version: str): """Set the software version info into the SoftwareDefinition table. :param software_version: The version of software :type software_version: str """ logger.debug(f"setting software version: {software_version}") session = get_session() try: sd = session.query(Software).one() except NoResultFound: sd = Software() session.add(sd) sd.software_version = software_version session.commit() session.close()
def refresh_interfaces(): """Refresh all interfaces. Update with current information.""" session = get_session() ap_present = False interfaces = get_interfaces() # update all interfaces.active to be False by default session.query(Interface).update({Interface.is_active: False}) for my_interface in interfaces: try: interface = session.query(Interface).filter_by( interface=my_interface).one() interface.is_active = True # see if there is an interface that is configured for an ap if interface.state == "ap": ap_present = True # must be a new interface so lets add it except NoResultFound: new_interface = Interface(my_interface) new_interface.is_active = True new_interface.is_for_fm = False new_interface.state = "dhcp" session.add(new_interface) session.commit() session.close() if ap_present: set_ap_mode() else: set_wpa_mode()
def first_setup(standalone): # noqa: C901 """First time setup. Load required data.""" # pylint: disable=too-many-statements,too-many-locals click.echo("First time setup") session = get_session() try: system = session.query(SystemSetup).one() except NoResultFound: system = SystemSetup() session.add(system) if system.first_setup: click.echo("Setup has already been run") if not click.confirm("Do you want to run first time setup again?"): session.close() return system.standalone_configuration = standalone system.first_setup = True system.first_setup_time = datetime.now() session.commit() session.close() if standalone: if click.confirm("Do you want to change the device name?"): name = click.prompt("Please enter a new device name") set_device_name(name) if click.confirm("Do you want to set hardware informations?"): hardware_version = click.prompt( "Enter the hardware version", default="pi3_0001" ) gb_count = click.prompt( "Enter the number of grainbin reader chips on the board", default=0 ) set_hardware_info(hardware_version, gb_count) if click.confirm("Do you want to set the sensor information?"): current_sensors = get_connected_sensors(values=True) click.echo("Current sensor information: ") for index, sensor in enumerate(current_sensors): click.echo( f"{index + 1}. Sensor: {sensor['name']} Temperature: {sensor['temperature']}" ) interior_sensor = click.prompt( "Select which sensor is the internal temperature", default=1 ) exterior_sensor = click.prompt( "Select which sensor is the external temperature", default=2 ) set_sensor_info(interior_sensor, exterior_sensor) if click.confirm("Do you want to set the software information?"): software_version = click.prompt("Enter the software version") set_software_info(software_version) if standalone: if click.confirm("Do you want to set details for the interfaces?"): interfaces = get_interfaces() x = 1 interface_details = [] for interface in interfaces: click.echo(f"{x}. {interface}") x = x + 1 interface_details.append(get_interface_details(interface)) set_interfaces(interface_details) initialize_device()
def delete(self, session=None, commit=True): """Remove the record from the database.""" if session is None: session = get_session() session.delete(self) return commit and session.commit()
def dbsession(): """Returns an sqlalchemy session.""" yield get_session()
class Meta: """Factory configuration.""" abstract = True sqlalchemy_session = get_session()
def create(cls, session=None, **kwargs): """Create a new record and save it the database.""" if session is None: session = get_session() instance = cls(**kwargs) return instance.save(session)