Magicae Speculo ~ Magic Mirror with homeautomation

This is my take on the popular Magic Mirror DYI project floating around the web

Sources on GitHub

Update 1.2.2017 – Added ventilation monitoring
Update 8.7.2017 Added Solar energy production info (Emphase Envoy-s)

I built this mirror mainly for my own home automation needs:

  1. To monitor ground heat pump statistics (Thermia ground heat pump)
  2. To see humidity/temperatures inside/outside of the house (TODO: to add more wireless sensors around the house )
  3. To see both mine and SO’s calendar easily.
  4. To monitor electricity usage of the House
  5. Monitor sleep statistics (Beddit)
  6. To see weather forecasts
  7. Ventilation monitoring/statistics (Enervent pingving)
  8. Solar energy: 4 x Emphase M250 microinverters with Envoy-s metering integration

and on my TODO list are:

  • Add Robomow robo lawn mower integration for schedule and notifications (Bluetooth integration)
  • Add more wireless temperature/humidity sensors (more rooms, greenhouse)
finished mirror with framing (need to hide the power cord still)

finished mirror with framing (need to hide the power cord still)

Ground heat pump animations depends on the status of the machine

 

If you have mouse you can also select to view the temperature graph or power usage graph

You can also select to view the temperature/humidity graph, power usage graph or ventilation values graph

Building the mirror/monitor frame

Source codes are available in GitHub: magicaespeculo

Materials:
(Prices are converted to usd on May, 2016)

  • 4mm x 640 x 380 (0.16inch x 25.2 x 15) one way class mirror (sgg MIRASTAR ) from local dealership Lasitalo 20€ ($22.5)
  • 27″ monitor Acer k272HL 149€ ($168)
  • Raspberry Pi 3 Model 3 36€ ($40) +charger 5€ ($6)
  • 16Gb microSD card 8€ ($9)
  • Mini PIR (to turn on/off monitor) 1.5€ ($2)
  • mics: Screws, housing brackets, glue, 5€ ($6)
  • Dark hazel – staining varnish and brushes 20€ ($22.50)
  • Wood for the frames: 11€ ($12.40)
    • Wooden angle list 3m long of 21x42mm (0.83×1.65inch, 10 feet long): note: images from the site where I bought the woods
    • front frame, keeps the mirror tightly in place and saved time as this is one finished block

       

    • Pine 3m long of 15x58mm (0.59×2.28inch, 10 feet long): note: images from the site where I bought the woods
    • body frame wood

Total price: 256€ ($288)

Workbench

I’m not in any way professional so my tools/skills are quite elementary.

my cheap ikea workbench

My cheap IKEA workbench with homemade sawing jig

Template for drilling holes for wooden caps

 

 

Used some glue to seal it tight

 

Assembled frame

After one layer of dark hazel staining varnish, used some manual sandpaper grinding and applied second layer. The dark hole is for PIR sensor

Front frame (angle list) glued and nailed to frame. 3 nails/side so it won’t slide off when mirror and monitor is pressed against it.

Mirror, monitor and frame setup:

  1. Removed the bezel from monitor with knife very carefully. It was very tight so needed to use quite much force to remove it.
  2. After the frame was built I just inserted the mirror against the wooded frame and added sofa leg paddings to the sides so it would hold the mirror better as there were 2mm extra room in the sides. (sofa leg paddings are those white rectangle pads)
  3. To hold the mirror I added wooden blocks which had again the sofa leg paddings against the mirror and clued and screwed them to the frame
  4. Then inserted monitor on top of the mirror and used housing brackets with sofa leg paddings to be tight fit. also the wood blocks were fitted so the monitor could not move sideways

Sofa leg paddings were quite useful to protect the mirror from too tight fastening

PIR sensor

The PIR sensor detects human presence and turns monitor on/off. This was done using PIR connected to Raspberry PI 3 Model B GPIO ports with interruptions (instead of polling and wasting CPU cycles)

Software:

Source codes can be downloaded from GitHub: here. This project is for my home automation monitoring. You can take what you need and modify as you need. I will continue to add features to this according my todo list and try to make it more robust for other projects as well. The Github page has all relevant information for setting up, running and configuring the code.

Note: This is not production level code, and was intended to use in my home network only. So haven’t thought about security aspects at all yet. Also this was just to meant to show calendar and date/weather so the Architecture was not thought from the start to cover all the things I ended up adding. Maybe some refactoring on the next versions (at least to come up with better database structure and maybe MQTT messaging)

I wanted to learn Node.js & JavaScript stuff more so I build it from scratch. I borrowed some ideas from existing “Magic Mirror” projects here and here

This is my home automation setup (will update the image when adding more stuff)

 

Please leave a comment/question.

10 Comments

  1. Reply
    Jeppis January 3, 2017

    Interesting project! One question. How did you attach front frame (= angle list) to body frame? Glue only? Some pics available maybe? Thanks!

  2. Reply
    admin January 3, 2017

    thanks for the input, I added new image to the post ( http://i.imgur.com/pj4wziC.jpg ) how it was done, but basically just glue and then 3 nails on each side.

  3. Reply
    Antti August 16, 2018

    Very interesting project! I have an old 24″ LCD display laying around and was thinking about doing something similar. I’m using Domoticz as the HA platform so the front-end would probably be something that fetches main chunk of the information from Domoticz.

    For ventilation we have an Enervent Pingvin and integrating that into the HA system is definitely something I’ll be looking into based on your python example. Are you only fetching the values from the device or have you implemented some way to control it as well (change fan speed, set status etc)?

    “TODO: Add Robomow robo lawn mower integration for schedule and notifications (Bluetooth integration”
    -> Any progress or even just ideas on how you plan to do this? We have Romobow MC500 and it would be nice to control it someway remotely (not just via phone app). But I haven’t found much info related to that. Might be quite tricky to reverse engineer the interface?

    • Reply
      admin August 19, 2018

      Hi and thanks,
      For enervent, I’m just polling the registers I’m interested in 60sec intervals. Enervent uses modbus (just like the wallmounted controls which enervent provides) uses the same protocol, so you could make python script to write the new values. I have the wallmount and I have seen I rarely need to adjust the enervent, so I didn’t implement the way to controll them. just don’t use the same slave/master address than the existing controller does. As it uses standard modbus, you could just look some examples how to write to modbus registers, I bet internet is full of them 🙂

      About the Robomow, I haven’t had the time and I don’t have currently any good bluetooth sniffer dongle/app, so mostlikely I don’t do do anything about that, maybe in coming years, but nothing planned at the moment

      • Reply
        Antti August 24, 2018

        Thanks for the reply, got the polling working quite easily with an extra RPi Zero I had lying around (already had a RS485 USB adapter as well). I used your check_ventilation.py as a reference, just modified the last part to update Domoticz virtual meters through its json API. My ultimate goal would be to integrate this to the HA system so that I could create different logic to e.g. turn on/off summer night cooling, over-pressure function (when starting the fire place or cooking) or just increase the ventilation if humidity or CO2 levels rise above certain levels etc. The wallmount is good as such but it would be nice to have more control 🙂

        I did a couple of initial tests but either the Enervent modbus implementation does not follow the standard in all places or there is something I’m missing already at the beginning. I was trying to read the coil status (as described here: https://minimalmodbus.readthedocs.io/en/master/apiminimalmodbus.html), e.g. for summer night cooling (1×0012) with Instrument.read_bit(12, 1) but according to the debug message it is receiving something else than expecting and therefore raises valueError. In theory, should it be as simple as that to read the coils – and thus also to write to them?

        • Reply
          admin August 24, 2018

          I asked from Enervent when I was implementing my python script, they said that Plug RJ4P4C wire into Enervent motherboard plug named “Freeway” (not OP1 or OP2), the Freeway port is standard modbus, but the OP1 or OP2 are not, they kinda works but gives timing erros as the data lenghts etc are not strictly modbus.

          The coil registers are 8bit longs, so it might not work with Instrument.read_bit(12,1) check with Instrument.read_register(12) instead.
          and to change the value, use the write_register(12,1) functions, you may need to try out different function codes if the default ones doesn’t work. Looking back at the documentation, I might also implement this this in couple of weeks if I have time to my mirror.

          I’m currently showing with operations status with register 3×0044:

          Tässä näkyy missä tilassa kone on, 0=Normaali tila, 1=Max jäähdytys, 2=Max lämmitys, 4=Hätäseis, 8=Seis, 16=Poissa, 32=Pitkään
          poissa, 46=Lämpötila tehostus, 128=CO2 tehostus, 256=Rh tehostus, 512=Tehostus, 1024=Ylipaineistus, 2048=Liesituuletin,
          4096=Keskuspölynimuri, 8192=SLP jäähdytys, 16384=Kesäyöjäähdytys, 32768=EDX sulatus. Kahden tilan ollessa aktiivina
          molemmat vetää ja rekisterin arvo on näiden tilojen summa. LSB bittivuonona luku help....

          and I’m converting the data to human readable format in the mirror frontend with this peace of code:
          https://github.com/teemuhirsikangas/magicaespeculo/blob/512dfaed12ee7f4a4ce5f38294a9e97b6fa36166/public/javascripts/ventilation.js#L61

          • Antti August 24, 2018

            Of course, by reading the Enervent modbus register list more carefully I should’ve picked up the note about 8bit coils. I just saw in some general documentation that coils would be 1bit which kinda made sense for that type of on/off functions. So I tried again with read_register and it works without errors. However, unfortunately the responses do not make too much sense to me…:) I read coils 1-12 a few times (without changing anything in Enervent) and got inconsistent results:
            1-5 = 0 (these were always the same, 0, even after changing the mode to e.g. “Away”)

            6-12 =>

            1st read:
            191
            215
            215
            219
            272
            65136
            65136

            2nd read:
            190
            214
            214
            219
            270
            65136
            65136

            3rd read:
            191
            215
            215
            219
            272
            65136
            65136

            I’m a bit lost on how I should interpret these and why the coil values vary between each read even if I do not change anything in Enervent. I’m hooked to the Freeway port and reading the registers for e.g. temperature work reliably.

            I’d be very interested to see what kind of results you get in case you have time to look at this.

          • admin August 26, 2018

            Seems that the minimalmodbus cannot read/write the coil registers, in your example data, it actually reading the Holdring registers.
            Also you could not set the function code to 1 to read the data. I tested this with another python lib pymodbus and there it seems to work ok for me 🙂

            here is the code I tested: I could read the coil registers ok, did not test about setting them but it should be trivial:
            https://pymodbus.readthedocs.io/en/v1.3.2/examples/synchronous-client.html


            #!/usr/bin/env python

            from pymodbus.client.sync import ModbusSerialClient as ModbusClient
            import logging
            logging.basicConfig()
            log = logging.getLogger()
            log.setLevel(logging.DEBUG)

            client = ModbusClient(method='rtu', port='/dev/ttyUSB0', timeout=1)
            client.connect()

            log.debug("Reading Coils")
            # starting register, number of registers, slave unit id
            rr = client.read_coils(12, 1, unit=0x01)

            hh = client.read_holding_registers(1,45,unit=0x01)

            print "holding registers:"
            print hh.registers

            print "coild register:"
            print rr.bits
            print("{}: {}".format("summernight cooling status:", rr.bits[0]))

            client.close()

          • Antti August 26, 2018

            Thanks a lot, works great! A lot of new possibilities to make the home a bit smarter just opened up…:)

            I was able to set different programs on/off, set the requested temperature etc. Out of what I tested, the only thing that didn’t work was setting the power (20-100, register 53). However, in the enervent modbus doc it says “IV-teho valitaan käyttöpaneelilta” which hints towards the direction that perhaps it cannot be set this way at all. To me this does not matter anyhow, I don’t think there’s too many good use cases for that as one should probably prefer to use the different programs to set the desired power level.

            Btw, with the coils I assume the rest of the bits are just “useless” extra to fill it to 8bits, the first [0] being therefore the only significant bit?

          • admin August 27, 2018

            Good it worked!, yes the fan speed does not fully work,
            I was able to set the fan speed value, and the new value was shown in the control box, but the new value was only taken into use once I pressed the + or – from the control terminal, and I could not find where apply the speed in the registers, maybe they are doing something which is not obvious from the register. The enervent support was helpfull, you could ask from them how the new speed value is taken into use. It’s true that you hardly even change this, as there are the boost, etc programs which are used instead.

            I assumed the same about using the coils 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *