Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not an issue as such, how to use on Raspi.. #20

Open
35nine opened this issue Apr 3, 2018 · 4 comments
Open

Not an issue as such, how to use on Raspi.. #20

35nine opened this issue Apr 3, 2018 · 4 comments

Comments

@35nine
Copy link

35nine commented Apr 3, 2018

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

@Ericmas001
Copy link
Contributor

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).
untitled

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
}

@gouldner
Copy link

gouldner commented Aug 16, 2018

@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?

@lumanga
Copy link

lumanga commented Jun 12, 2019

@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??

@jgroezin
Copy link

jgroezin commented Oct 8, 2020

Thanks for the code and the explanation. Running your python on RPI. Still figuring this out a bit but defintely controls my HVAC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants