FarmBot / farmbot-mqtt-py

An MQTT wrapper for FarmBot written in Python
MIT License
42 stars 23 forks source link

Certain web app commands aren't being read #12

Closed mvilsoet closed 2 years ago

mvilsoet commented 2 years ago

Hello, I have a question regarding CeleryScript. In another issue, we received code that monitors all commands sent to the web app. If I click, for example, "read tool verification" on the Web App, the following pasted script prints the corresponding CeleryScript.

If you ever want to know what commands the web app is sending, you can listen via:

import json
import paho.mqtt.client as mqtt
from farmbot import FarmbotToken

token = FarmbotToken.download_token("email", "password")
token = json.loads(token)['token']

def on_connect(client, userdata, flags, rc):
    client.subscribe(f"bot/{token['unencoded']['bot']}/from_clients")

def on_message(client, userdata, msg):
    print(json.dumps(json.loads(msg.payload), indent=4))

client = mqtt.Client()
client.username_pw_set(
    token['unencoded']['bot'],
    password=token['encoded'])
client.connect(token['unencoded']['mqtt'])
client.on_connect = on_connect
client.on_message = on_message
client.loop_forever()

However, when we try to perform Web App commands such as "Apply Garden," the script doesn't print any commands to the terminal. Do you know of any way we can use python to perform the tasks: "Apply Garden," "Delete all Plants," and how to edit an already saved garden?

gabrielburnworth commented 2 years ago

The script you referenced is for listening to commands the Web App sends to the FarmBot device. For requests the Web App makes to the API (such as garden actions), you can listen in by using the 'network' tab of the web developer tools in your browser.

Here's a starting point for using Python to manage the gardens in your Web App account, where garden and plant ids can be found by navigating to the item in the Web App and copying the number in the URL (or by using a requests.get() request using the corresponding request_url):

import json
import requests
from farmbot import FarmbotToken

token = FarmbotToken.download_token('email', 'password')
token = json.loads(token)['token']['encoded']
headers = {'Authorization': f'Bearer {token}',
           'content-type': 'application/json'}

# Delete plants
plant_ids = [1, 2, 3]
csv_plant_ids = ','.join([str(id) for id in plant_ids])
request_url = f'https://my.farm.bot/api/points/{csv_plant_ids}'
response = requests.delete(request_url, headers=headers)
print(response.status_code)

# Edit Garden: Add new plant
saved_garden_id = 1
request_url = 'https://my.farm.bot/api/plant_templates/'
new_plant_payload = {
    'saved_garden_id': saved_garden_id,
    'name': 'Apple',
    'openfarm_slug': 'apple',
    'radius': 25,
    'x': 100,
    'y': 100,
    'z': 0,
}
response = requests.post(request_url, headers=headers, json=new_plant_payload)
print(response.status_code)

# Edit Garden: Delete plant
plant_template_id = 1
request_url = f'https://my.farm.bot/api/plant_templates/{plant_template_id}'
response = requests.delete(request_url, headers=headers)
print(response.status_code)

# Apply Garden
saved_garden_id = 1
request_url = f'https://my.farm.bot/api/saved_gardens/{saved_garden_id}/apply'
response = requests.patch(request_url, headers=headers)
print(response.status_code)
kulbir-ahluwalia commented 2 years ago

Thanks for your help! We were able to execute all of these instructions.

Could you please also let us know how to:

  1. Create a new garden
  2. Delete a garden
  3. Read saved garden id
  4. Find the plant template id of some plant

We would appreciate any help. Thanks!

kulbir-ahluwalia commented 2 years ago

Using https://developer.farm.bot/v15/docs/web-app/api-docs.html,

I was able to solve "1.Create a new garden" as follows:

#############################################
###### create a new garden
#############################################
points_response = requests.request(
    method='POST',
    url=HOST + '/api/saved_gardens',
    headers={
        'content-type': 'application/json',
        'Authorization': "bearer " + TOKEN
    },
    json={
        "name": "Kale2"
    })

print(points_response.json())

Please let me know if there is a better way. Thanks!

kulbir-ahluwalia commented 2 years ago
  1. and 4. are also solved:
  fb, RAW_TOKEN = get_token(args)
  jsonResponse_loads_only = json.loads(RAW_TOKEN)
  HOST = "https://my.farm.bot"
  token = jsonResponse_loads_only['token']['encoded']
  headers = {'Authorization': f'Bearer {token}',
             'content-type': 'application/json'}

  request_url = f'https://my.farm.bot/api/plant_templates/'
  response = requests.get(request_url, headers=headers)
  print(response.json())

  response_json = response.json()
  print(response.status_code)

  for plant_template in response_json:
      print(plant_template['id'], plant_template['saved_garden_id'])