import pystache
import json
import sys
import os

meta = [
    ('io.button', 'KY-004', 'Push button', ['io.knob'], '**N.B.** a button behaves differently from a switch'),
    ('io.knob', 'KY-040', 'Rotary encoder with push button', ['io.button'], ''),
    ('io.distance', 'Distance', 'Ultrasonic distance sensor', [], ''),
    ('io.temperature', 'KY-001', 'Temperature sensor', [], ''),
    ('io.humidity', 'KY-015', 'Relative humidity sensor', [], 'DHT11 based, but not used as temparature sensor because of the poor resolution.'),
    ('io.hallswitch', 'KY-003', 'Hall magnetic sensor module', [], ''),
    ('io.vibrationsensor', 'KY-002', 'Vibration sensor module', ['io.tiltswitch', 'io.knocksensor'], 'Vibration, tilt and schock sensors are very similar, using the same default pin and have identical configs. Schematic shown only for the vibration sensor module.'),
    ('io.tiltswitch', 'KY-020', 'Tilt switch', ['io.vibrationsensor', 'io.knocksensor'], ''),
    ('io.knocksensor', 'KY-031', 'Schock sensor module', ['io.vibrationsensor', 'io.tiltswitch'], ''),
    ('io.lightbreaker', 'KY-010', 'Optical gap switch', [], ''),
    ('io.light', 'LED', 'Digital out (LED with resistor)', [], 'Serial resistor 220 Ohm needed for LED.'),
    ('io.pwm', 'PWM', 'PWM out (LED with resistor)', [], 'Serial resistor 220 Ohm needed for LED.'),
    ('io.buzzer', 'KY-012', 'Active buzzer module', [], 'Active buzzer 2.5kHz.\n\n **N.B.** The labels on the PCB are wrong on many of these, try swapping the leads if there is no beeping.'),
]

templ = """
### {{{title}}} ([{{{device}}}][{{{device}}}]) <a name="_{{{device}}}"></a>
{{#comment}}

{{comment}}
{{/comment}}

Default pin(s): {{{pins}}}
{{#has_image}}

![{{{device}}}][{{{device}}}-img]
{{/has_image}}

Config entry in `capabilities` list:

```
{{{config}}}
```
{{#snippet}}

Usage example:

```
{{{snippet}}}
```
{{/snippet}}
{{#conflicts}}

Conflicts: {{{conflicts}}}
{{/conflicts}}
"""

preamble = """
# Calvin Sensor Kit v0.1

This file is autogenerated from `calvin.config` and `images/` using the `sensor-kit-doc.py` utility.
Process with markdown to generate a nicely formatted document, e.g.;

    markdown readme.md > readme.html

 or use the version on the [Calvin wiki](https://github.com/EricssonResearch/calvin-base/wiki/SensorKit)


## Compatibility

Type 3 - Model A+, B+, Pi Zero, Pi2B, Pi3B

- 40 pin expansion header (J8).
- Hardware revision numbers of 16 or greater.
- User GPIO 2-27 (0 and 1 are reserved).

### Pinout

    ...--------------------------------+
                                       |
          GPIO  pin pin  GPIO          |
               +-------+               |
    3V3     -  | 1    2|   -   5V      |
    SDA     2  | 3    4|   -   5V      |
    SCL     3  | 5    6|   -   GND     |
            4  | 7    8|  14   TXD     |
    GND     -  | 9   10|  15   RXD     |
    ce1    17  |11   12|  18   ce0     |
           27  |13   14|   -   GND     |
           22  |15   16|  23           |
    3V3     -  |17   18|  24           |
    MOSI   10  |19   20|   -   GND     |
    MISO    9  |21   22|  25           |
    SCLK   11  |23   24|   8   CE0     |
    GND     -  |25   26|   7   CE1     |
    N/A     0  |27   28|   1   N/A     |
            5  |29   30|   -   GND     |
            6  |31   32|  12           |
           13  |33   34|   -   GND     |
    miso   19  |35   36|  16   ce2     |
           26  |37   38|  20   mosi    |
    GND     -  |39   40|  21   sclk    |
               +-------+               .
                                       .
                                       .


## Configuring devices

First a word about Calvin sensors on a Rasberry Pi: The preferred way to package IoT-devices in Calvin's world is units with a single capability, or a few capabilities, each with its own attributes to resolve actor placement in a real world deployment.

That said, Raspberry Pi's are a great way to get started with Calvin, and we have defined a default sensor-kit with parts that are easy to find in stores and online. In order to maximize the number of simultaneous sensors that can be used and to avoid conflicts between sensors (in terms of pins used) we also provide default pin configurations for the sensor-kit below.

Note that we are using GPIO pin numbering, not board pin numbering below.

Almost all sensors can be attached to a single Raspberry Pi at the same time, and if there is a conflict it is stated in the documentation below.

With each sensor, its default config entry is shown. The full config file is part of the sensor-kit code that can be found in `calvin/examples/sensor-kit`. That config file makes a good starting point for any customization that a user might want to do.

There is still room for expansion, since GPIO pins 6, 14, 15, and 27 are as of yet undefined, although using them as follows would make sense:

- pin 6  : Digital out
- pin 27 : Digital in
- pin 14 : TxD
- pin 15 : RxD

## Devices

"""

postamble = """

[KY-001]: http://arduinomodules.info/ky-001-temperature-sensor-module/
[KY-002]: http://arduinomodules.info/ky-002-vibration-switch-module/
[KY-003]: http://arduinomodules.info/ky-003-hall-magnetic-sensor-module/
[KY-004]: http://arduinomodules.info/ky-004-key-switch-module/
[KY-005]: http://arduinomodules.info/ky-005-infrared-transmitter-sensor-module/
[KY-006]: http://arduinomodules.info/ky-006-passive-buzzer-module/
[KY-008]: http://arduinomodules.info/ky-008-laser-transmitter-module/
[KY-009]: http://arduinomodules.info/ky-009-rgb-full-color-led-smd-module/
[KY-010]: http://arduinomodules.info/ky-010-photo-interrupter-module/
[KY-011]: http://arduinomodules.info/ky-011-two-color-led-module-3mm/
[KY-012]: http://arduinomodules.info/ky-012-active-buzzer-module/
[KY-013]: http://arduinomodules.info/ky-013-analog-temperature-sensor-module/
[KY-015]: http://arduinomodules.info/ky-015-temperature-humidity-sensor-module/
[KY-016]: http://arduinomodules.info/ky-016-rgb-full-color-led-module/
[KY-017]: http://arduinomodules.info/ky-016-rgb-full-color-led-module/
[KY-018]: http://arduinomodules.info/ky-018-photoresistor-module/
[KY-019]: http://arduinomodules.info/ky-019-5v-relay-module/
[KY-020]: https://tkkrlab.nl/wiki/Arduino_KY-020_Tilt_switch_module
[KY-021]: https://tkkrlab.nl/wiki/Arduino_KY-021_Mini_magnetic_reed_modules
[KY-022]: http://arduinomodules.info/ky-022-infrared-receiver-module/
[KY-023]: https://tkkrlab.nl/wiki/Arduino_KY-023_XY-axis_joystick_module
[KY-024]: https://tkkrlab.nl/wiki/Arduino_KY-024_Linear_magnetic_Hall_sensors
[KY-025]: https://tkkrlab.nl/wiki/Arduino_KY-025_Reed_module
[KY-026]: https://tkkrlab.nl/wiki/Arduino_KY-026_Flame_sensor_module
[KY-027]: https://tkkrlab.nl/wiki/Arduino_KY-027_Magic_light_cup_module
[KY-028]: http://auseparts.com.au/index.php?route=product/product&product_id=77
[KY-029]: https://tkkrlab.nl/wiki/Arduino_KY-029_Yin_Yi_2-color_LED_module_3MM
[KY-031]: https://tkkrlab.nl/wiki/Arduino_KY-031_Knock_Sensor_module
[KY-032]: https://tkkrlab.nl/wiki/Arduino_KY-032_Obstacle_avoidance_sensor_module
[KY-033]: http://arduinosensors.nl/index.php?route=product/product&path=20&product_id=79
[KY-034]: https://tkkrlab.nl/wiki/Arduino_KY-034_Automatic_flashing_colorful_LED_module
[KY-035]: https://tkkrlab.nl/wiki/Arduino_KY-035_Class_Bihor_magnetic_sensor
[KY-036]: https://tkkrlab.nl/wiki/Arduino_KY-036_Metal_touch_sensor_module
[KY-037]: https://tkkrlab.nl/wiki/Arduino_KY-037_Sensitive_microphone_sensor_module
[KY-038]: https://tkkrlab.nl/wiki/Arduino_KY-038_Microphone_sound_sensor_module
[KY-039]: https://tkkrlab.nl/wiki/Arduino_KY-039_Detect_the_heartbeat_module
[KY-040]: https://tkkrlab.nl/wiki/Arduino_KY-040_Rotary_encoder_module
[Distance]: https://www.sparkfun.com/products/13959

[KY-001-img]: images/KY-001.png
[KY-002-img]: images/KY-002.png
[KY-003-img]: images/KY-003.png
[KY-004-img]: images/KY-004.png
[KY-010-img]: images/KY-010.png
[KY-012-img]: images/KY-012.png
[KY-015-img]: images/KY-015.png
[KY-040-img]: images/KY-040.png
[Distance-img]: images/Distance.png
[LED-img]: images/LED.png
[PWM-img]: images/PWM.png
"""

with open("calvin.conf") as f:
    d = json.load(f)
    caps = d['calvinsys']['capabilities']

print preamble

for k, device, title, conflicts, comment in meta:
    if k.startswith('sys.timer'):
        continue
    try:
        v = caps[k]
    except:
        sys.stderr.write("Skipping {}".format(k))
        continue
    entry = {}
    entry['title'] = title
    entry['comment'] = comment
    entry['device'] = device
    entry['config'] = "{}: {}".format(k, json.dumps(v, indent=4))
    _, snippet = k.rsplit('.', 1)
    try:
        snippet_file = snippet + ".calvin"
        with open(snippet_file) as f:
            entry['snippet'] = f.read()
    except:
        pass
    attrs = v.get('attributes', {})
    pins = [v for k,v in attrs.iteritems() if k.endswith('pin')]
    if pins:
        entry['pins'] = ','.join([str(p) for p in sorted(pins)])
    entry['conflicts'] = ', '.join(conflicts)
    if os.path.exists('images/' + device + '.png'):
        entry['has_image'] = True
    print pystache.render(templ, entry)

print postamble

