Coverage for farmbot_sidecar_starter_pack/main.py: 100%

139 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-09-01 12:19 -0700

1""" 

2Farmbot class. 

3""" 

4 

5from .state import State 

6from .functions.api import ApiConnect 

7from .functions.basic_commands import BasicCommands 

8from .functions.broker import BrokerConnect 

9from .functions.camera import Camera 

10from .functions.information import Information 

11from .functions.jobs import JobHandling 

12from .functions.messages import MessageHandling 

13from .functions.movements import MovementControls 

14from .functions.peripherals import Peripherals 

15from .functions.resources import Resources 

16from .functions.tools import ToolControls 

17 

18VERSION = "1.3.0" 

19 

20 

21class Farmbot(): 

22 """Farmbot class.""" 

23 __version__ = VERSION 

24 

25 def __init__(self): 

26 self.state = State() 

27 

28 # Initialize other components without the token initially 

29 self.api = ApiConnect(self.state) 

30 self.basic = BasicCommands(self.state) 

31 self.broker = BrokerConnect(self.state) 

32 self.camera = Camera(self.state) 

33 self.info = Information(self.state) 

34 self.jobs = JobHandling(self.state) 

35 self.messages = MessageHandling(self.state) 

36 self.movements = MovementControls(self.state) 

37 self.peripherals = Peripherals(self.state) 

38 self.resources = Resources(self.state) 

39 self.tools = ToolControls(self.state) 

40 

41 def set_verbosity(self, value): 

42 """Set output verbosity level.""" 

43 self.state.verbosity = value 

44 

45 def set_timeout(self, duration, key="listen"): 

46 """Set timeout value in seconds.""" 

47 if key == "all": 

48 for timeout_key in self.state.timeout: 

49 self.state.timeout[timeout_key] = duration 

50 else: 

51 self.state.timeout[key] = duration 

52 

53 def set_token(self, token): 

54 """Set FarmBot authorization token.""" 

55 self.state.token = token 

56 

57 # api.py 

58 

59 def get_token(self, email, password, server="https://my.farm.bot"): 

60 """Get FarmBot authorization token. Server is 'https://my.farm.bot' by default.""" 

61 return self.api.get_token(email, password, server) 

62 

63 # basic_commands.py 

64 

65 def wait(self, duration): 

66 """Pauses execution for a certain number of milliseconds.""" 

67 return self.basic.wait(duration) 

68 

69 def e_stop(self): 

70 """Emergency locks (E-stops) the Farmduino microcontroller.""" 

71 return self.basic.e_stop() 

72 

73 def unlock(self): 

74 """Unlocks a locked (E-stopped) device.""" 

75 return self.basic.unlock() 

76 

77 def reboot(self): 

78 """Reboots the FarmBot OS and re-initializes the device.""" 

79 return self.basic.reboot() 

80 

81 def shutdown(self): 

82 """Shuts down the FarmBot OS and turns the device off.""" 

83 return self.basic.shutdown() 

84 

85 # broker.py 

86 

87 def connect_broker(self): 

88 """Establish persistent connection to send messages via message broker.""" 

89 return self.broker.connect() 

90 

91 def disconnect_broker(self): 

92 """Disconnect from the message broker.""" 

93 return self.broker.disconnect() 

94 

95 def publish(self, message): 

96 """Publish message to the message broker.""" 

97 return self.broker.publish(message) 

98 

99 def listen(self, channel="#", duration=None): 

100 """Listen to a message broker channel for the provided duration in seconds.""" 

101 return self.broker.listen(channel, duration) 

102 

103 # camera.py 

104 

105 def calibrate_camera(self): 

106 """Performs camera calibration. This action will reset camera calibration settings.""" 

107 return self.camera.calibrate_camera() 

108 

109 def take_photo(self): 

110 """Takes photo using the device camera and uploads it to the web app.""" 

111 return self.camera.take_photo() 

112 

113 # information.py 

114 

115 def api_get(self, endpoint, database_id=None): 

116 """Get information about a specific endpoint.""" 

117 return self.info.api_get(endpoint, database_id) 

118 

119 def api_patch(self, endpoint, new_data, database_id=None): 

120 """Change information contained within an endpoint.""" 

121 return self.info.api_patch(endpoint, new_data, database_id) 

122 

123 def api_post(self, endpoint, new_data): 

124 """Create new information contained within an endpoint.""" 

125 return self.info.api_post(endpoint, new_data) 

126 

127 def api_delete(self, endpoint, id=None): 

128 """Delete information contained within an endpoint.""" 

129 return self.info.api_delete(endpoint, id) 

130 

131 def safe_z(self): 

132 """Returns the highest safe point along the z-axis.""" 

133 return self.info.safe_z() 

134 

135 def garden_size(self): 

136 """Returns size of garden bed.""" 

137 return self.info.garden_size() 

138 

139 def group(self, group_id=None): 

140 """Returns all group info or single by id.""" 

141 return self.info.group(group_id) 

142 

143 def curve(self, curve_id=None): 

144 """Returns all curve info or single by id.""" 

145 return self.info.curve(curve_id) 

146 

147 def measure_soil_height(self): 

148 """Use the camera to determine soil height at the current location.""" 

149 return self.info.measure_soil_height() 

150 

151 def read_status(self): 

152 """Returns the FarmBot status tree.""" 

153 return self.info.read_status() 

154 

155 def read_sensor(self, sensor_name): 

156 """Reads the given sensor.""" 

157 return self.info.read_sensor(sensor_name) 

158 

159 # jobs.py 

160 

161 def get_job(self, job_str=None): 

162 """Retrieves the status or details of the specified job.""" 

163 return self.jobs.get_job(job_str) 

164 

165 def set_job(self, job_str, status_message, value): 

166 """Initiates or modifies job with given parameters.""" 

167 return self.jobs.set_job(job_str, status_message, value) 

168 

169 def complete_job(self, job_str): 

170 """Marks job as completed and triggers any associated actions.""" 

171 return self.jobs.complete_job(job_str) 

172 

173 # messages.py 

174 

175 def log(self, message_str, message_type="info", channel="ticker"): 

176 """Sends new log message via the API.""" 

177 return self.messages.log(message_str, message_type, channel) 

178 

179 def message(self, message_str, message_type="info", channel="ticker"): 

180 """Sends new log message via the message broker.""" 

181 return self.messages.message(message_str, message_type, channel) 

182 

183 def debug(self, message_str): 

184 """Sends debug message used for developer information or troubleshooting.""" 

185 return self.messages.debug(message_str) 

186 

187 def toast(self, message_str): 

188 """Sends a message that pops up on the user interface briefly.""" 

189 return self.messages.toast(message_str) 

190 

191 # movements.py 

192 

193 def move(self, x, y, z): 

194 """Moves to the specified (x, y, z) coordinate.""" 

195 return self.movements.move(x, y, z) 

196 

197 def set_home(self, axis="all"): 

198 """Sets the current position as the home position for a specific axis.""" 

199 return self.movements.set_home(axis) 

200 

201 def find_home(self, axis="all", speed=100): 

202 """Moves the device to the home position for a specified axis.""" 

203 return self.movements.find_home(axis, speed) 

204 

205 def find_axis_length(self, axis="all"): 

206 """Finds the length of a specified axis.""" 

207 return self.movements.find_axis_length(axis) 

208 

209 def get_xyz(self): 

210 """Returns the current (x, y, z) coordinates of the FarmBot.""" 

211 return self.movements.get_xyz() 

212 

213 def check_position(self, user_x, user_y, user_z, tolerance): 

214 """Verifies position of the FarmBot within specified tolerance range.""" 

215 return self.movements.check_position(user_x, user_y, user_z, tolerance) 

216 

217 # peripherals.py 

218 

219 def control_servo(self, pin, angle): 

220 """Set servo angle between 0-100 degrees.""" 

221 return self.peripherals.control_servo(pin, angle) 

222 

223 def control_peripheral(self, peripheral_name, value, mode=None): 

224 """Set peripheral value and mode.""" 

225 return self.peripherals.control_peripheral(peripheral_name, value, mode) 

226 

227 def toggle_peripheral(self, peripheral_name): 

228 """Toggles the state of a specific peripheral between `on` and `off`.""" 

229 return self.peripherals.toggle_peripheral(peripheral_name) 

230 

231 def on(self, pin_number): 

232 """Turns specified pin number `on` (100%).""" 

233 return self.peripherals.on(pin_number) 

234 

235 def off(self, pin_number): 

236 """Turns specified pin number `off` (0%).""" 

237 return self.peripherals.off(pin_number) 

238 

239 # resources.py 

240 

241 def sequence(self, sequence_name): 

242 """Executes a predefined sequence.""" 

243 return self.resources.sequence(sequence_name) 

244 

245 def get_seed_tray_cell(self, tray_name, tray_cell): 

246 """Identifies and returns the location of specified cell in the seed tray.""" 

247 return self.resources.get_seed_tray_cell(tray_name, tray_cell) 

248 

249 def detect_weeds(self): 

250 """Scans the garden to detect weeds.""" 

251 return self.resources.detect_weeds() 

252 

253 def lua(self, code_snippet): 

254 """Executes custom Lua code snippets to perform complex tasks or automations.""" 

255 return self.resources.lua(code_snippet) 

256 

257 def if_statement(self, variable, operator, value, then_sequence_name=None, else_sequence_name=None, named_pin_type=None): 

258 """Performs conditional check and executes actions based on the outcome.""" 

259 return self.resources.if_statement(variable, operator, value, then_sequence_name, else_sequence_name, named_pin_type) 

260 

261 def assertion(self, code, assertion_type, recovery_sequence_name=None): 

262 """Evaluates an expression.""" 

263 return self.resources.assertion(code, assertion_type, recovery_sequence_name) 

264 

265 # tools.py 

266 

267 def mount_tool(self, tool_str): 

268 """Mounts the given tool and pulls it out of assigned slot.""" 

269 return self.tools.mount_tool(tool_str) 

270 

271 def dismount_tool(self): 

272 """Dismounts the currently mounted tool into assigned slot.""" 

273 return self.tools.dismount_tool() 

274 

275 def water(self, plant_id): 

276 """Moves to and waters plant based on age and assigned watering curve.""" 

277 return self.tools.water(plant_id) 

278 

279 def dispense(self, milliliters, tool_name, pin): 

280 """Dispenses user-defined amount of liquid in milliliters.""" 

281 return self.tools.dispense(milliliters, tool_name, pin)