diff --git a/dist/iotAmak-0.0.7-py3-none-any.whl b/dist/iotAmak-0.0.7-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..6b8729469c70282fe1274145a88acef11cfe9f1a Binary files /dev/null and b/dist/iotAmak-0.0.7-py3-none-any.whl differ diff --git a/iotAmak/tool/__init__.py b/iotAmak/agent/__init__.py similarity index 100% rename from iotAmak/tool/__init__.py rename to iotAmak/agent/__init__.py diff --git a/iotAmak/agent/agent.py b/iotAmak/agent/agent.py new file mode 100644 index 0000000000000000000000000000000000000000..4af7fb9e13b14583ade030d795f85664a4d72f49 --- /dev/null +++ b/iotAmak/agent/agent.py @@ -0,0 +1,68 @@ +""" +Agent class file +""" +import json +import sys +import pathlib +from typing import Dict + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.base.schedulable import Schedulable +from iotAmak.agent.base_agent import BaseAgent + + +class Agent(Schedulable, BaseAgent): + """ + base class for agent + """ + + def __init__(self, arguments: str) -> None: + + arguments: Dict = json.loads(arguments) + + broker_ip: str = arguments.get("broker_ip") + identifier: int = int(arguments.get("identifier")) + seed: int = int(arguments.get("seed")) + broker_username: str = str(arguments.get("broker_username")) + broker_password: str = str(arguments.get("broker_password")) + + Schedulable.__init__(self, broker_ip, "Agent" + str(identifier), broker_username, broker_password) + BaseAgent.__init__(self, identifier, seed) + + self.subscribe("scheduler/agent/wakeup", self.wake_up) + + self.on_initialization() + + self.publish("cycle_done", "") + + def publish(self, topic: str, message) -> None: + """ + publish a message on the topic + :param topic: str + :param message: content of the message + """ + self.client.publish("agent/" + str(self.id) + "/" + topic, message) + + def run(self) -> None: + """ + Main method of the agent + """ + while not self.exit_bool: + + self.wait() + if self.exit_bool: + return + + self.on_cycle_begin() + + self.on_perceive() + + self.on_decide() + + self.on_act() + + self.on_cycle_end() + + self.publish("metric", str(self.send_metric())) + self.publish("cycle_done", "") + self.nbr_cycle += 1 diff --git a/iotAmak/agent/async_agent.py b/iotAmak/agent/async_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..a2653d552e6e29ca63e450d1a5103fe6dafeb169 --- /dev/null +++ b/iotAmak/agent/async_agent.py @@ -0,0 +1,57 @@ +""" +AsyncAgent class file +""" +import pathlib +import sys +import json +from typing import Dict + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.base.async_controlable import AsyncControlable +from iotAmak.agent.base_agent import BaseAgent + + +class AsyncAgent(AsyncControlable, BaseAgent): + """ + Async class for agent + """ + + def __init__(self, arguments: str) -> None: + + arguments: Dict = json.loads(arguments) + + broker_ip: str = arguments.get("broker_ip") + identifier: int = int(arguments.get("identifier")) + seed: int = int(arguments.get("seed")) + broker_username: str = str(arguments.get("broker_username")) + broker_password: str = str(arguments.get("broker_password")) + wait_delay: float = float(arguments.get("wait_delay")) + + AsyncControlable.__init__( + self, + broker_ip, + "Agent" + str(identifier), + broker_username, + broker_password, + wait_delay + ) + BaseAgent.__init__(self, identifier, seed) + + self.on_initialization() + + def publish(self, topic: str, message) -> None: + """ + publish a message on the topic + :param topic: str + :param message: content of the message + """ + self.client.publish("agent/" + str(self.id) + "/" + topic, message) + + def behaviour(self) -> None: + self.on_cycle_begin() + self.on_perceive() + self.on_decide() + self.on_act() + self.on_cycle_end() + self.publish("metric", str(self.send_metric())) + diff --git a/iotAmak/agent/async_communicating_agent.py b/iotAmak/agent/async_communicating_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..fb221b413c9cbbe810d1060f27cad3751fcf808a --- /dev/null +++ b/iotAmak/agent/async_communicating_agent.py @@ -0,0 +1,16 @@ +import pathlib +import sys + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.agent.async_agent import AsyncAgent +from iotAmak.agent.base_communicating_agent import BaseCommunicatingAgent + + +class AsyncCommunicatingAgent(AsyncAgent, BaseCommunicatingAgent): + """ + Agent class that can communicate + """ + + def __init__(self, arguments: str) -> None: + AsyncAgent.__init__(self, arguments) + BaseCommunicatingAgent.__init__(self) diff --git a/iotAmak/agent.py b/iotAmak/agent/base_agent.py similarity index 52% rename from iotAmak/agent.py rename to iotAmak/agent/base_agent.py index 8ccb58e98cad2db0dbdaf60962f57b54ee0b4af7..4d31dd2b8c7a1f3aefa598139eaf385604cf6749 100644 --- a/iotAmak/agent.py +++ b/iotAmak/agent/base_agent.py @@ -1,140 +1,81 @@ """ -Agent class file +Base Agent class file """ -import json import random from ast import literal_eval from typing import Dict, List -import sys -import pathlib -sys.path.insert(0, str(pathlib.Path(__file__).parent)) - -from iotAmak.tool.schedulable import Schedulable - - -class Agent(Schedulable): +class BaseAgent: """ base class for agent """ - def __init__(self, arguments: str) -> None: - - arguments: Dict = json.loads(arguments) - - broker_ip: str = arguments.get("broker_ip") - identifier: int = int(arguments.get("identifier")) - seed: int = int(arguments.get("seed")) - broker_username: str = str(arguments.get("broker_username")) - broker_password: str = str(arguments.get("broker_password")) - + def __init__(self, identifier: int, seed: int) -> None: self.id: int = identifier - random.seed(seed + 10 + self.id) - Schedulable.__init__(self, broker_ip, "Agent" + str(self.id), broker_username, broker_password) - - self.subscribe("scheduler/agent/wakeup", self.wake_up) - self.neighbors: List[Dict] = [] self.next_neighbors: List[Dict] = [] self.subscribe("amas/agent/" + str(self.id) + "/neighbor", self.add_neighbor) - self.on_initialization() - - self.publish("cycle_done", "") - print("init done") - def on_initialization(self) -> None: """ This method will be executed at the end of __init__() """ pass - def add_neighbor(self, client, userdata, message) -> None: - """ - Called when the agent, receive metrics - put the metric in a list that will be rad during on_perceive - param message: metric (dict) of the neighbor - """ - result: Dict = literal_eval(message.payload.decode("utf-8")) - self.next_neighbors.append(result) - - def log(self, message: str) -> None: - """ - Convenient method to log things (will be printed in the amas's stdout - :param message: - """ - self.client.publish( - "agent/" + str(self.id) + "/log", - "[AGENT] " + str(self.id) + " : " + message - ) - - def publish(self, topic: str, message) -> None: - """ - publish a message on the topic - :param topic: str - :param message: content of the message - """ - self.client.publish("agent/" + str(self.id) + "/" + topic, message) - def on_cycle_begin(self) -> None: """ This method will be executed at the start of each cycle """ - self.log("on_cycle_begin") + pass def on_perceive(self) -> None: """ Method that should be used to open the neighbor metrics and use them """ - self.log("on_perceive") + pass def on_decide(self) -> None: """ Should be override """ - self.log("on_decide") + pass def on_act(self) -> None: """ Should be override """ - self.log("on_act") + pass def on_cycle_end(self) -> None: """ This method will be executed at the end of each cycle """ - self.log("on_cycle_end") + pass - def send_metric(self) -> Dict: + def add_neighbor(self, client, userdata, message) -> None: """ - Should be override if the neighbor need to be aware of any other info, should be a dict + Called when the agent, receive metrics + put the metric in a list that will be rad during on_perceive + param message: metric (dict) of the neighbor """ - return {"id": self.id} + result: Dict = literal_eval(message.payload.decode("utf-8")) + self.next_neighbors.append(result) - def run(self) -> None: + def log(self, message: str) -> None: """ - Main method of the agent + Convenient method to log things (will be printed in the amas's stdout + :param message: """ - while not self.exit_bool: - - self.wait() - if self.exit_bool: - return - - self.on_cycle_begin() - - self.on_perceive() - - self.on_decide() - - self.on_act() - - self.on_cycle_end() + self.client.publish( + "agent/" + str(self.id) + "/log", + "[AGENT] " + str(self.id) + " : " + message + ) - self.publish("metric", str(self.send_metric())) - self.publish("cycle_done", "") - self.nbr_cycle += 1 + def send_metric(self) -> Dict: + """ + Should be override if the neighbor need to be aware of any other info, should be a dict + """ + return {"id": self.id} diff --git a/iotAmak/communicating_agent.py b/iotAmak/agent/base_communicating_agent.py similarity index 86% rename from iotAmak/communicating_agent.py rename to iotAmak/agent/base_communicating_agent.py index 0600ea957d83888b181750ec2b1389e413a3835f..81cc8d1aab8fa4da57f5c8faf0d537c431b2149f 100644 --- a/iotAmak/communicating_agent.py +++ b/iotAmak/agent/base_communicating_agent.py @@ -4,20 +4,17 @@ import sys from ast import literal_eval from typing import List, Any -sys.path.insert(0, str(pathlib.Path(__file__).parent)) +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.agent.mail import Mail -from iotAmak.agent import Agent -from iotAmak.tool.mail import Mail - -class CommunicatingAgent(Agent): +class BaseCommunicatingAgent: """ Agent class that can communicate """ - def __init__(self, arguments: str) -> None: + def __init__(self) -> None: self.mailbox: List[Mail] = [] - Agent.__init__(self, arguments) self.subscribe("agent/" + str(self.id) + "/mail", self.receive_mail) def receive_mail(self, client, userdata, message) -> None: @@ -57,7 +54,3 @@ class CommunicatingAgent(Agent): put the mail in the front of the mailbox """ self.mailbox = [mail] + self.mailbox - - - - diff --git a/iotAmak/agent/communicating_agent.py b/iotAmak/agent/communicating_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..8cebdfa5be381a19587fe4aa682500686fe9acfa --- /dev/null +++ b/iotAmak/agent/communicating_agent.py @@ -0,0 +1,16 @@ +import pathlib +import sys + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.agent.agent import Agent +from iotAmak.agent.base_communicating_agent import BaseCommunicatingAgent + + +class CommunicatingAgent(Agent, BaseCommunicatingAgent): + """ + Agent class that can communicate + """ + + def __init__(self, arguments: str) -> None: + Agent.__init__(self, arguments) + BaseCommunicatingAgent.__init__(self) diff --git a/iotAmak/tool/mail.py b/iotAmak/agent/mail.py similarity index 100% rename from iotAmak/tool/mail.py rename to iotAmak/agent/mail.py diff --git a/iotAmak/amas/__init__.py b/iotAmak/amas/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/iotAmak/amas/amas.py b/iotAmak/amas/amas.py new file mode 100644 index 0000000000000000000000000000000000000000..391bdbb484dec3be6d3ddbe0bb6c99b9191aadff --- /dev/null +++ b/iotAmak/amas/amas.py @@ -0,0 +1,79 @@ +""" +Amas class +""" +import json +from ast import literal_eval + +import sys +import pathlib + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.ssh_module.remote_client import RemoteClient +from iotAmak.base.schedulable import Schedulable +from iotAmak.amas.base_amas import BaseAmas + + +class Amas(Schedulable, BaseAmas): + """ + Amas class + """ + + def __init__(self, arguments: str) -> None: + + arguments = json.loads(arguments) + + broker_ip: str = arguments.get("broker_ip") + clients: str = arguments.get("clients") + seed: int = int(arguments.get("seed")) + broker_username: str = str(arguments.get("broker_username")) + broker_password: str = str(arguments.get("broker_password")) + iot_path: str = str(arguments.get("iot_path")) + true_client = [RemoteClient(i.get("hostname"), i.get("user"), i.get("password")) for i in literal_eval(clients)] + + Schedulable.__init__(self, broker_ip, "Amas", broker_username, broker_password) + self.subscribe("scheduler/schedulable/wakeup", self.wake_up) + BaseAmas.__init__(self, + broker_ip, + broker_username, + broker_password, + seed, + iot_path, + true_client) + + self.client.publish("amas/action_done", "") + + def on_cycle_begin(self) -> None: + """ + This method will be executed at the start of each cycle + """ + pass + + def on_cycle_end(self) -> None: + """ + This method will be executed at the end of each cycle + """ + pass + + def run(self) -> None: + """ + Main function of the amas class + """ + self.push_agent() + + while not self.exit_bool: + + self.wait() + if self.exit_bool: + return + + self.publish("amas/all_metric", str(self.agents_metric)) + self.on_cycle_begin() + self.client.publish("amas/action_done", "") + + # agent cycle + + self.wait() + self.on_cycle_end() + self.client.publish("amas/action_done", "") + + self.nbr_cycle += 1 diff --git a/iotAmak/amas/async_amas.py b/iotAmak/amas/async_amas.py new file mode 100644 index 0000000000000000000000000000000000000000..34abb213a8b7d41ab20221c4899ded31d87726f2 --- /dev/null +++ b/iotAmak/amas/async_amas.py @@ -0,0 +1,114 @@ +import pathlib +import sys +import json +from ast import literal_eval +from typing import List + + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.amas.base_amas import BaseAmas +from iotAmak.base.async_controlable import AsyncControlable +from iotAmak.ssh_module.remote_client import RemoteClient +from iotAmak.ssh_module.ssh_client import Cmd + + +class AsyncAmas(AsyncControlable, BaseAmas): + """ + Amas class + """ + + def __init__(self, arguments: str) -> None: + + arguments = json.loads(arguments) + + broker_ip: str = arguments.get("broker_ip") + clients: str = arguments.get("clients") + seed: int = int(arguments.get("seed")) + broker_username: str = str(arguments.get("broker_username")) + broker_password: str = str(arguments.get("broker_password")) + iot_path: str = str(arguments.get("iot_path")) + wait_delay: float = float(arguments.get("wait_delay")) + + true_client = [RemoteClient(i.get("hostname"), i.get("user"), i.get("password")) for i in literal_eval(clients)] + + AsyncControlable.__init__( + self, + broker_ip, + "Amas", + broker_username, + broker_password, + wait_delay + ) + BaseAmas.__init__(self, + broker_ip, + broker_username, + broker_password, + seed, + iot_path, + true_client) + + self.push_agent() + + def on_metric(self) -> None: + """ + This method will be executed everytime a metric is send + """ + pass + + def add_agent( + self, + experience_name: str, + client_ip: str = None, + agent_name: str = "agent.py", + args: List = None + ) -> None: + """ + Function that need to be called to create a new agent + :param experience_name: name of the experience folder + :param client_ip: if the agent should be created in a specific device, you can specify an ip address, + otherwise the Amas will try to share the work between the devices + :param agent_name: if using multiple kind of agent, you can specify the relative path in the experiment + directory to the agent file to use + :param args: if any argument is needed to initiate the new agent + :return: None + """ + if args is None: + args = [] + + arg_dict = { + "broker_ip": str(self.broker_ip), + "seed": self.seed, + "identifier": self.next_id, + "broker_username": self.broker_username, + "broker_password": self.broker_password, + "wait_delay": self.wait_delay + } + + command = "nohup python " + command += "\'" + self.iot_path + experience_name + "/" + agent_name + "\' \'" + command += json.dumps(arg_dict) + "\' " + for arg in args: + command += str(arg) + " " + command += "&" + + if client_ip is None: + # find the most suitable pi + i_min = 0 + for elem in range(len(self.clients)): + if len(self.agents_cmd[i_min]) > len(self.agents_cmd[elem]): + i_min = elem + self.agents_cmd[i_min].append(Cmd(command)) + else: + have_found = False + for i_client in range(len(self.clients)): + if self.clients[i_client].hostname == client_ip: + self.agents_cmd[i_client].append(Cmd(command)) + have_found = True + break + if not have_found: + self.agents_cmd[0].append(Cmd(command)) + + self.subscribe("agent/" + str(self.next_id) + "/metric", self.agent_metric) + + self.client.publish("amas/agent/new", self.next_id) + self.next_id += 1 \ No newline at end of file diff --git a/iotAmak/amas.py b/iotAmak/amas/base_amas.py similarity index 63% rename from iotAmak/amas.py rename to iotAmak/amas/base_amas.py index d335985a42748eb028d8a15a840c78307adadfd2..c3da4e0e80706e5ed92560374f6ce4f0a9987ccf 100644 --- a/iotAmak/amas.py +++ b/iotAmak/amas/base_amas.py @@ -1,56 +1,48 @@ -""" -Amas class -""" import json -from ast import literal_eval -from typing import List, Dict - +import random import sys import pathlib -import random - -sys.path.insert(0, str(pathlib.Path(__file__).parent)) - -from iotAmak.tool.remote_client import RemoteClient -from iotAmak.tool.schedulable import Schedulable -from iotAmak.tool.ssh_client import SSHClient, Cmd +from ast import literal_eval +from typing import List, Dict +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.ssh_module.ssh_client import SSHClient, Cmd +from iotAmak.ssh_module.remote_client import RemoteClient -class Amas(Schedulable, SSHClient): - """ - Amas class - """ - def __init__(self, arguments: str) -> None: +class BaseAmas(SSHClient): - arguments = json.loads(arguments) + def __init__( + self, + broker_ip: str, + broker_username: str, + broker_password: str, + seed: int, + iot_path: str, + clients: List[RemoteClient] + ): + self.broker_ip: str = broker_ip + self.broker_username: str = broker_username + self.broker_password: str = broker_password - self.broker_ip: str = arguments.get("broker_ip") - clients: str = arguments.get("clients") - self.seed: int = int(arguments.get("seed")) - self.broker_username: str = str(arguments.get("broker_username")) - self.broker_password: str = str(arguments.get("broker_password")) - iot_path: str = str(arguments.get("iot_path")) + self.next_id: int = 0 + self.seed: int = seed random.seed(self.seed) - Schedulable.__init__(self, self.broker_ip, "Amas", self.broker_username, self.broker_password) + self.agents_cmd: List[List[Cmd]] = [[] for _ in range(len(clients))] - true_client = [RemoteClient(i.get("hostname"), i.get("user"), i.get("password")) for i in literal_eval(clients)] - - SSHClient.__init__(self, true_client, iot_path) - - self.subscribe("scheduler/schedulable/wakeup", self.wake_up) - - self.next_id: int = 0 - - self.agents_cmd: List[List[Cmd]] = [[] for _ in range(len(self.clients))] + SSHClient.__init__(self, clients, iot_path) self.on_initialization() self.on_initial_agents_creation() self.agents_metric: List[Dict] = [{} for _ in range(self.next_id)] - self.client.publish("amas/action_done", "") + def on_initialization(self) -> None: + """ + This method will be executed at the end of __init__() + """ + pass def on_initial_agents_creation(self) -> None: """ @@ -83,11 +75,11 @@ class Amas(Schedulable, SSHClient): "seed": self.seed, "identifier": self.next_id, "broker_username": self.broker_username, - "broker_password": self.broker_password + "broker_password": self.broker_password } command = "nohup python " - command += "\'" + self.iot_path + experience_name + "/"+agent_name+"\' \'" + command += "\'" + self.iot_path + experience_name + "/" + agent_name + "\' \'" command += json.dumps(arg_dict) + "\' " for arg in args: command += str(arg) + " " @@ -138,45 +130,3 @@ class Amas(Schedulable, SSHClient): result = literal_eval(message.payload.decode("utf-8")) agent_id = result.get("id") self.agents_metric[agent_id] = result - - def on_initialization(self) -> None: - """ - This method will be executed at the end of __init__() - """ - pass - - def on_cycle_begin(self) -> None: - """ - This method will be executed at the start of each cycle - """ - pass - - def on_cycle_end(self) -> None: - """ - This method will be executed at the end of each cycle - """ - pass - - def run(self) -> None: - """ - Main function of the amas class - """ - self.push_agent() - - while not self.exit_bool: - - self.wait() - if self.exit_bool: - return - - self.publish("amas/all_metric", str(self.agents_metric)) - self.on_cycle_begin() - self.client.publish("amas/action_done", "") - - # agent cycle - - self.wait() - self.on_cycle_end() - self.client.publish("amas/action_done", "") - - self.nbr_cycle += 1 diff --git a/iotAmak/base/__init__.py b/iotAmak/base/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/iotAmak/base/async_controlable.py b/iotAmak/base/async_controlable.py new file mode 100644 index 0000000000000000000000000000000000000000..c0c71b80b51aee29bb0916f0c700ff59a0317890 --- /dev/null +++ b/iotAmak/base/async_controlable.py @@ -0,0 +1,92 @@ +""" +MQTT client class file +""" +import sys +import pathlib +from threading import Semaphore +from time import sleep + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.base.mqtt_client import MqttClient + + +class AsyncControlable(MqttClient): + """ + Base class to any instance that need to interact with the broker + """ + + def __init__( + self, + broker_ip: str, + client_id: str, + broker_username: str, + broker_password: str, + wait_delay: float + ): + MqttClient.__init__(self, broker_ip, client_id, broker_username, broker_password) + + # exit + self.exit_bool: bool = False + self.subscribe("ihm/exit", self.exit_procedure) + + # pause + self.paused: bool = True + self.pause_semaphore = Semaphore(0) + self.subscribe("ihm/pause", self.pause) + self.subscribe("ihm/unpause", self.unpause) + + # time to wait + self.wait_delay: float = wait_delay + + self.nbr_cycle: int = 0 + + def exit_procedure(self, client, userdata, message) -> None: + """ + Called by the Ihm to exit as soon as possible + """ + self.exit_bool = True + + def pause(self, client, userdata, message) -> None: + """ + Function called when the IHM pause the scheduler + """ + self.paused = True + + def unpause(self, client, userdata, message) -> None: + """ + Function called when the IHM unpause the scheduler + """ + self.paused = False + self.pause_semaphore.release() + + def wait(self) -> None: + """ + If the element is paused, wait until unpause was received + """ + if not self.paused: + return + self.pause_semaphore.acquire() + + def behaviour(self) -> None: + """ + method to override + """ + return + + def run(self) -> None: + """ + Main method of the client + """ + + while not self.exit_bool: + # wait to be unpause + self.wait() + + # check the need to exit + if self.exit_bool: + return + + self.behaviour() + + sleep(self.wait_delay) + self.nbr_cycle += 1 diff --git a/iotAmak/tool/mqtt_client.py b/iotAmak/base/mqtt_client.py similarity index 100% rename from iotAmak/tool/mqtt_client.py rename to iotAmak/base/mqtt_client.py diff --git a/iotAmak/tool/schedulable.py b/iotAmak/base/schedulable.py similarity index 89% rename from iotAmak/tool/schedulable.py rename to iotAmak/base/schedulable.py index 0a2730446df42961b68d420fbac4134879f3ea71..33ec1ff512b9df28eaf8813473797b33ffccfd06 100644 --- a/iotAmak/tool/schedulable.py +++ b/iotAmak/base/schedulable.py @@ -8,7 +8,7 @@ import threading sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) -from iotAmak.tool.mqtt_client import MqttClient +from iotAmak.base.mqtt_client import MqttClient class Schedulable(MqttClient): @@ -31,15 +31,12 @@ class Schedulable(MqttClient): Called by the scheduler to wake up the schedulable """ self.semaphore.release() - # print("Waked up") def wait(self) -> None: """ Basic wait method """ - # print("Waiting") self.semaphore.acquire() - # print("End wait") def exit_procedure(self, client, userdata, message) -> None: """ diff --git a/iotAmak/env/__init__.py b/iotAmak/env/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/iotAmak/env/async_env.py b/iotAmak/env/async_env.py new file mode 100644 index 0000000000000000000000000000000000000000..6d0fceda540ccc95df8fd3b8ba19bf1774b3c8ac --- /dev/null +++ b/iotAmak/env/async_env.py @@ -0,0 +1,36 @@ +""" +Environment class +""" +import json +import sys +import pathlib + +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.env.base_env import BaseEnv +from iotAmak.base.async_controlable import AsyncControlable + + +class AsyncEnvironment(BaseEnv, AsyncControlable): + """ + Environment class + """ + + def __init__(self, arguments: str) -> None: + + arguments = json.loads(arguments) + + broker_ip: str = arguments.get("broker_ip") + seed: int = int(arguments.get("seed")) + broker_username: str = str(arguments.get("broker_username")) + broker_password: str = str(arguments.get("broker_password")) + wait_delay: float = float(arguments.get("wait_delay")) + + AsyncControlable.__init__( + self, + broker_ip, + "Env", + broker_username, + broker_password, + wait_delay + ) + BaseEnv.__init__(self, seed) diff --git a/iotAmak/env/base_env.py b/iotAmak/env/base_env.py new file mode 100644 index 0000000000000000000000000000000000000000..905f8fe723365af0d91462c24a7311751dd5aa0d --- /dev/null +++ b/iotAmak/env/base_env.py @@ -0,0 +1,13 @@ +import random + + +class BaseEnv: + def __init__(self, seed: int) -> None: + random.seed(seed + 1) + self.on_initialization() + + def on_initialization(self) -> None: + """ + This method will be executed at the end of __init__() + """ + pass diff --git a/iotAmak/environment.py b/iotAmak/env/environment.py similarity index 83% rename from iotAmak/environment.py rename to iotAmak/env/environment.py index b054cbce1c02e029460c69fdc97c85de139da7db..68bbbc17dcd77be91e4dbb56df6e755a97f47453 100644 --- a/iotAmak/environment.py +++ b/iotAmak/env/environment.py @@ -7,11 +7,11 @@ import sys import pathlib sys.path.insert(0, str(pathlib.Path(__file__).parent)) +from iotAmak.env.base_env import BaseEnv +from iotAmak.base.schedulable import Schedulable -from iotAmak.tool.schedulable import Schedulable - -class Environment(Schedulable): +class Environment(Schedulable, BaseEnv): """ Environment class """ @@ -25,22 +25,11 @@ class Environment(Schedulable): broker_username: str = str(arguments.get("broker_username")) broker_password: str = str(arguments.get("broker_password")) - random.seed(seed + 1) - Schedulable.__init__(self, broker_ip, "Env", broker_username, broker_password) - self.subscribe("scheduler/schedulable/wakeup", self.wake_up) - - self.on_initialization() - + BaseEnv.__init__(self, seed) self.client.publish("env/action_done", "") - def on_initialization(self) -> None: - """ - This method will be executed at the end of __init__() - """ - pass - def on_cycle_begin(self) -> None: """ This method will be executed at the start of each cycle diff --git a/iotAmak/ihm/__init__.py b/iotAmak/ihm/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/iotAmak/tool/confi_reader.py b/iotAmak/ihm/confi_reader.py similarity index 90% rename from iotAmak/tool/confi_reader.py rename to iotAmak/ihm/confi_reader.py index 5070707f8f3489928519b3870e7632e9d5503888..f761a9c78d982bce57668e2c3905ce1fd9cf80a0 100644 --- a/iotAmak/tool/confi_reader.py +++ b/iotAmak/ihm/confi_reader.py @@ -4,7 +4,7 @@ import pathlib sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) -from iotAmak.tool.remote_client import RemoteClient +from iotAmak.ssh_module.remote_client import RemoteClient def read_ssh(path): diff --git a/iotAmak/ihm.py b/iotAmak/ihm/ihm.py similarity index 93% rename from iotAmak/ihm.py rename to iotAmak/ihm/ihm.py index 11b4f190f04962ce01c8e4289f65e01fc9bb03ef..5032f41834a5c734e7a016512c75e54dd22c2dd8 100644 --- a/iotAmak/ihm.py +++ b/iotAmak/ihm/ihm.py @@ -9,9 +9,9 @@ import pathlib sys.path.insert(0, str(pathlib.Path(__file__).parent)) -from iotAmak.tool.confi_reader import read_ssh, read_broker -from iotAmak.tool.mqtt_client import MqttClient -from iotAmak.tool.ssh_client import SSHClient, Cmd +from iotAmak.ihm.confi_reader import read_ssh, read_broker +from iotAmak.base.mqtt_client import MqttClient +from iotAmak.ssh_module.ssh_client import SSHClient, Cmd class Ihm(MqttClient, SSHClient): @@ -29,10 +29,10 @@ class Ihm(MqttClient, SSHClient): def loading(self): print("[LOADING]") print("Check experiment:") - print(" | -> agent.py : ", path.exists("./agent.py")) - print(" | -> amas.py : ", path.exists("./amas.py")) + print(" | -> agent.py : ", path.exists("../agent/agent.py")) + print(" | -> amas.py : ", path.exists("../amas/amas.py")) print(" | -> env.py : ", path.exists("./env.py")) - if path.exists("./agent.py") and path.exists("./amas.py") and path.exists("./env.py"): + if path.exists("../agent/agent.py") and path.exists("../amas/amas.py") and path.exists("./env.py"): self.experiment_loaded = True print("Experiment loaded") else: diff --git a/iotAmak/scheduler/__init__.py b/iotAmak/scheduler/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/iotAmak/scheduler.py b/iotAmak/scheduler/scheduler.py similarity index 97% rename from iotAmak/scheduler.py rename to iotAmak/scheduler/scheduler.py index 19e21ead3e01ca697db0c230f40a2dd5d5abcf2e..d5f22374b54becec8fafe7c8fb8cb96e23852200 100644 --- a/iotAmak/scheduler.py +++ b/iotAmak/scheduler/scheduler.py @@ -7,9 +7,8 @@ from time import sleep, time import sys import pathlib -sys.path.insert(0, str(pathlib.Path(__file__).parent)) - -from iotAmak.tool.schedulable import Schedulable +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) +from iotAmak.base.schedulable import Schedulable class Scheduler(Schedulable): diff --git a/iotAmak/ssh_module/__init__.py b/iotAmak/ssh_module/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/iotAmak/tool/remote_client.py b/iotAmak/ssh_module/remote_client.py similarity index 100% rename from iotAmak/tool/remote_client.py rename to iotAmak/ssh_module/remote_client.py diff --git a/iotAmak/tool/ssh_client.py b/iotAmak/ssh_module/ssh_client.py similarity index 91% rename from iotAmak/tool/ssh_client.py rename to iotAmak/ssh_module/ssh_client.py index 858df6dccd0c6336ba77046e2a76fe2f8e952a8c..a208519b893ed36ef16803776b23e6f61b354061 100644 --- a/iotAmak/tool/ssh_client.py +++ b/iotAmak/ssh_module/ssh_client.py @@ -9,8 +9,7 @@ from pexpect import pxssh sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) -from iotAmak.tool.remote_client import RemoteClient - +from iotAmak.ssh_module.remote_client import RemoteClient class Cmd: @@ -19,15 +18,14 @@ class Cmd: self.do_print = do_print self.prefix = prefix - class SSHClient: def __init__(self, clients: List[RemoteClient], iot_path: str): - self.clients = clients - self.iot_path = iot_path + self.clients: List[RemoteClient] = clients + self.iot_path: str = iot_path - def run_cmd(self, client: int, cmd: list, repeat: bool = False) -> list[str]: - ret = [] + def run_cmd(self, client: int, cmd: list, repeat: bool = False) -> List[str]: + ret: List[str] = [] try: s = pxssh.pxssh() dest = self.clients[client] @@ -48,7 +46,7 @@ class SSHClient: self.run_cmd(client, cmd, True) return ret - def update(self, experiment_name, path_to_experiment): + def update(self, experiment_name: str, path_to_experiment: str): for client in self.clients: transport = paramiko.Transport((client.hostname, 22)) transport.connect(username=client.user, password=client.password) diff --git a/setup.py b/setup.py index c88411713ae214b66f3a100c867e7e5b73574f30..fc4ebef897683b5adf56cb036be306c88c90b48e 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages setup( name='iotAmak', packages=find_packages(), - version='0.0.6', + version='0.0.7', description='AmakFramework in python', author='SMAC - GOYON Sebastien', install_requires=[