Open 35nine opened 6 years ago
Hi ! I personnally use it everyday with a rpi-zero-w with Minibian installed.
The important thing is:
When you use "hvac = Mitsubishi(23, LogLevel.ErrorsOnly)", 23 is the GPIO number, not the PIN number
My IR led is on GPIO 23 (Pin 16).
I will give you more info than you need, so you can reproduce something close to my setup. This is my setup: https://github.com/Ericmas001/pi-adventures/blob/master/general/minibian_initial_setup.md
Then I installed:
sudo apt-get install git -y
sudo apt-get install python python-dev python-pip python-rpi.gpio pigpio -y
sudo pip install git+https://github.com/Ericmas001/HVAC-IR-Control
sudo pip install pigpio
sudo pip install flask
I use flask and a little webservice to control it, but that is not madatory. My IR led is on GPIO 23 (Pin 16).
app.py
#!/usr/bin/python
import logging
from logging.handlers import RotatingFileHandler
from datetime import datetime, time
from flask import Flask, request, jsonify
from flask.json import JSONEncoder
import handler
class CustomJSONEncoder(JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, time):
return obj.isoformat()
return obj.__dict__
class MyFlask(Flask):
def make_response(self, rv):
if hasattr(rv, 'response') and rv.response is None:
return super(MyFlask, self).make_response(rv)
if hasattr(rv, 'new_url') and rv.new_url is not None:
return super(MyFlask, self).make_response(rv)
return super(MyFlask, self).make_response(jsonify(rv))
app = MyFlask(__name__)
app.json_encoder = CustomJSONEncoder
@app.route('/config/', methods=['GET'])
def list_config():
return handler.list_config(app)
@app.route('/hvac/off/', methods=['GET'])
def power_off():
return handler.power_off(app)
@app.route('/hvac/on/', methods=['GET'])
def power_on():
return handler.send_last_command(app)
@app.route('/hvac/command/', methods=['POST'])
def send_command():
return handler.send_command(app, request.json)
@app.route('/last/command/', methods=['GET'])
def last_command():
return handler.last_command(app)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=4242)
handler.py
#!/usr/bin/python
from hvac_ircontrol.ir_sender import LogLevel
from hvac_ircontrol.mitsubishi import Mitsubishi, ClimateMode, FanMode, VanneVerticalMode, VanneHorizontalMode, ISeeMode, AreaMode, PowerfulMode, Constants
from models import *
import inspect
import json
from collections import namedtuple
import datetime
import traceback
import os
path = "/hvac/last_config.json"
def list_config(app):
res = AvailableCommands()
res.climate_modes = __list_attributes(ClimateMode)
res.isee_modes = __list_attributes(ISeeMode)
res.powerful_modes = __list_attributes(PowerfulMode)
res.vanne_horizontal_modes = __list_attributes(VanneHorizontalMode)
res.fan_modes = __list_attributes(FanMode)
res.vanne_vertical_modes = __list_attributes(VanneVerticalMode)
res.area_modes = __list_attributes(AreaMode)
res.min_temp = Constants.MinTemp
res.max_temp = Constants.MaxTemp
return res
def power_off(app):
hvac = Mitsubishi(23, LogLevel.ErrorsOnly)
hvac.power_off()
return "It was powered OFF"
def last_command(app):
command = HvacCommand()
if os.path.isfile(path):
with open(path, 'r') as content_file:
data = json.loads(content_file.read())
command.from_json(data)
return command
def send_command(app, data):
command = HvacCommand()
command.from_json(data)
return __send_command(app, command)
def send_last_command(app):
return __send_command(app, last_command(app))
def __send_command(app, command):
try:
hvac = Mitsubishi(23, LogLevel.Minimal)
args = dict(
climate_mode=__get_value(ClimateMode, command.climate_mode),
temperature=command.temperature,
fan_mode=__get_value(FanMode, command.fan_mode),
vanne_vertical_mode=__get_value(VanneVerticalMode, command.vanne_vertical_mode),
vanne_horizontal_mode=__get_value(VanneHorizontalMode, command.vanne_horizontal_mode),
isee_mode=__get_value(ISeeMode, command.isee_mode),
area_mode=__get_value(AreaMode, command.area_mode),
start_time = __get_time_value(command.start_time),
end_time = __get_time_value(command.end_time),
powerful=__get_value(PowerfulMode, command.powerful_mode))
hvac.send_command(**args)
cfg = open(path, "w")
cfg.write(command.to_json())
return HvacCommandResponse(True,command,args)
except:
app.logger.error("There was an error: {0}".format(traceback.format_exc()))
return HvacCommandResponse(False,data,"There was an error: {0}".format(traceback.format_exc()))
def __list_attributes(my_type):
return [a[0] for a in inspect.getmembers(my_type, lambda c:not(inspect.isroutine(c))) if not a[0].startswith('_')]
def __get_value(my_type, my_value):
return [a[1] for a in inspect.getmembers(my_type, lambda c:not(inspect.isroutine(c))) if a[0] == my_value][0]
def __get_time_value(my_value):
if my_value is None or my_value < 0 or my_value >= 24:
return None
return datetime.time(int(my_value)//1, int((my_value*100)%100))
models.py
import json
class AvailableCommands:
def __init__(self):
self.climate_modes = []
self.isee_modes = []
self.powerful_modes = []
self.vanne_horizontal_modes = []
self.fan_modes = []
self.vanne_vertical_modes = []
self.area_modes = []
self.min_temp = -1
self.max_temp = -1
class HvacCommandResponse:
def __init__(self, success, command, decoded):
self.success = success
self.command = command
self.decoded_command = decoded
class HvacCommand:
def __init__(self):
self.climate_mode = "Cold"
self.isee_mode = "ISeeOn"
self.powerful_mode = "PowerfulOff"
self.vanne_horizontal_mode = "NotSet"
self.fan_mode = "Auto"
self.vanne_vertical_mode = "Auto"
self.area_mode = "NotSet"
self.temperature = 21
self.start_time = None
self.end_time = None
def from_json(self, data):
self.climate_mode = data["climate_mode"]
self.isee_mode = data["isee_mode"]
self.powerful_mode = data["powerful_mode"]
self.vanne_horizontal_mode = data["vanne_horizontal_mode"]
self.fan_mode = data["fan_mode"]
self.vanne_vertical_mode = data["vanne_vertical_mode"]
self.area_mode = data["area_mode"]
self.temperature = data["temperature"]
self.start_time = data["start_time"]
self.end_time = data["end_time"]
def to_json(self):
return json.dumps(self.__dict__, sort_keys=True, indent=4, separators=(',', ': '))
and some communication examples:
I/REQUEST: http://localhost:4242/hvac/off/
I/METHOD: GET
I/RESPONSE: "It was powered OFF"
I/REQUEST: http://localhost:4242/hvac/on/
I/DATA:
{
"climate_mode": "Hot",
"isee_mode": "ISeeOn",
"powerful_mode": "PowerfulOff",
"vanne_horizontal_mode": "NotSet",
"fan_mode": "Auto",
"vanne_vertical_mode": "Auto",
"area_mode": "Full",
"temperature": 21,
"start_time": -1,
"end_time": -1
}
I/METHOD: POST
I/RESPONSE:
{
"command": {
"area_mode": "Full",
"climate_mode": "Hot",
"end_time": -1,
"fan_mode": "Auto",
"isee_mode": "ISeeOn",
"powerful_mode": "PowerfulOff",
"start_time": -1,
"temperature": 21,
"vanne_horizontal_mode": "NotSet",
"vanne_vertical_mode": "Auto"
},
"decoded_command": {
"area_mode": 128,
"climate_mode": 8,
"end_time": null,
"fan_mode": 128,
"isee_mode": 64,
"powerful": 0,
"start_time": null,
"temperature": 21,
"vanne_horizontal_mode": 0,
"vanne_vertical_mode": 64
},
"success": true
}
@Ericmas001 Great instructions for Raspberry! Thanks. If I run your Flask code as root it works fine. But if I run it as pi I get an error. and nothing is sent. (Code still returns success but I tested and signal isn't sent) 2018-08-16 20:55:53 gpioSetMode: pigpio uninitialised, call gpioInitialise() 2018-08-16 20:55:53 gpioWaveClear: pigpio uninitialised, call gpioInitialise() Error in clearing wave! 127.0.0.1 - - [16/Aug/2018 20:55:53] "GET /hvac/off/ HTTP/1.1" 200 -
my user "pi" is in the group gpio and I am updated to the latest version of stretch. Any idea how to make this work running as pi instead of having a web service running as root?
@Ericmas001
Dear Sir,
I have Raspberry pi 3 with Raspbian LITE OS.
I have Broadlink Mini R3 connected to my WiFi. I have IP and MAC of Broadlink inserted into the .py file.
I have installed "sudo pip3 install broadlink" and all the files of this project.
If I do in terminal:
pi@CyberPiLITE:$ python3 SendHVACCmdToRM2.py
I receive:
26022601703a0e2a0e2a0e0d0e0d0e0d0e2a0e0d0e0d0e2a0e2a0e0d0e2a0e0d0e0d0e2a0e2a0e0d0e2a0e2a0e0d0e0d0e2a0e0d0e0d0e2a0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e2a0e2a0e0d0e0d0e0d0e2a0e0d0e2a0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e2a0e2a0e0d0e0d0e2a0e2a0e0d0e0d0e0d0e0d0e2a0e2a0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e0d0e2a0e2a0e0d0e2a0e0d0e2a0e0d0e0d0f0032020d
so python works!
Even if I do: pi@CyberPiLITE: $ python3 SendHVACCmdToRM2.py -h I receive: ` usage: SendHVACCmdToRM2.py [-h] [-t HVAC_TEMPERATURE] [-p] [-c HVAC_CLIMATE_CODE] [-Vv HVAC_VANNE_V_CODE] [-F HVAC_FAN_MODE] [--version]
Short sample python HVAC_IR command sender to Broadlink RM2 Mini optional arguments: -h, --help show this help message and exit -t HVAC_TEMPERATURE, --temperature HVAC_TEMPERATURE Set HVAC Temperature in Celcius, Ex: 21 -p, --power HVAC Power, default = Power Off -c HVAC_CLIMATE_CODE, --climate HVAC_CLIMATE_CODE Define Climate Code : C=Cold, H=HOT -Vv HVAC_VANNE_V_CODE, --vanne_vertical HVAC_VANNE_V_CODE Define Vertical Vanne Mode : A=Automatic, S=Swing, B=Bottom, T:Top -F HVAC_FAN_MODE, --fan HVAC_FAN_MODE Define Fan speed : A=Automatic, L=Low, M=Middle, F=Fast, S=Silent ` So I don't understand the command to use after to let my MSD-FD25 work
For example POWER ON, COLD, 23°C, van AUTO, fan AUTO??
Thanks for the code and the explanation. Running your python on RPI. Still figuring this out a bit but defintely controls my HVAC.
Hi. Am banging my head on a wall here, have attempted to use the python port but no ir activity seen from ir led used. I have pigpio installed, have used the pip install command from the readme and then am lost, I admit not to know how to use this within python. I have run the mits demo code, it throws up no errors as such, just no ir light emitted. IR led is known to be fine, lirc commands all fine. If anyone can offer some extra guidance how to use, would be fantastic. Thanks