Giter VIP home page Giter VIP logo

openhr20's Introduction

OpenHR20

Build Status

This repository contains open firmware for Honeywell Rondostat HR20 and similar, Atmega-MCU based radiator thermostats. It is not based on the original, proprietary firmware, but rather a complete rewrite. It was started around 2008 by Jiri Dobry and Dario Carluccio, but has been changed and extended by many people since.

Currently supported thermostats are:

  • HR20
  • HR25
  • THERMOTRONIC

Main improvements of this firmware are addition of wireless and/or wired communication with central hub.

Original repository is still available at SourceForge. Original description page with a lot of interesting information is available in German here.

Compiling

As installing this firmware needs flashing a program to the thermostat MCU with hardware programmer, at least basic understanding of working with AVR MCUs and some additional hardware is required.

To compile the sources, avr compatible gcc crosscompiler is required. On many linux distributions, you can install this via packages, e.g. on debian based distros, installing "gcc-avr" package should install the whole required toolchain. For flashing, "avrdude" package is also required. For Windows, the WinAVR package should get you all the tools needed.

To compile the default configuration - HR20 version with RFM12B radio:

make

To compile the sources without wireless extension:

make RFM=0

To compile with predefined REVision ID

make REV=-DREVISION=\\\"123456_XYZ\\\"

To compile with hardware window open contact

make HW_WINDOW_DETECTION=1

thermotronic HW

make HW=THERMOTRONIC

PINOUT HR20

The externally accesible connector on HR20/25 thermostats allows direct connection to the MCU for flashing via JTAG, or for wired communication. The connector layout is:

ATmega169PV (<Port,Pin>/<No.>)
Vcc RXD(PE0/02) TDO(PF6/55) TMS(PF5/56) /RST(PG5/20)
GND TDI(PF7/54) TXD(PE1/03) TCK(PF4/57) (PE2/04)

openhr20's People

Contributors

bruce33 avatar c-mm avatar dlemper avatar dlemperfuchs avatar filipek92 avatar fra87 avatar kickertom avatar machoel avatar maltep avatar matthijskooijman avatar piontec avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openhr20's Issues

[Q] How to enable RS232 only?

Hello,
I want to use the thermostat in wired setup.
Can I kindly ask someone to help me configure OpenHR20?

thanks.

Unstable clock on master breaks encryption

Last week I did some debugging of the connection problems I had in the place, where the master is running via an LTE connection. Long time I suspected that the LTE-800 radios where breaking the connection since they work at 856Mhz. It turns out that this seems not to be the case.

Instead because of the varying ping times, a slow clock and therefor lagging ntp sync on the openwrt master, the valves send their data a bit too early with the "new" encryption key for the second, but the master with it's slow clock still uses the "old" encryption key of the previous second.

I'm quite unsure what to do about that. One could either try to decode the packet with "more" keys (as in second-1, second, second+1) or shift the communication window to the middle of the second, providing a wider margin for correct decryption.

I also have not fully understood, why the valves don't sync fast enough to the masters timestamps to not drift too far away.

Any hints or ideas in what direction i should work?

2015-11-15 18:14:23      @22.98 ERR5d7c 10 17 a6 80 1c bf d5 e3 40 d2...
2015-11-15 18:14:22      @21.98 ERR5d7b 10 16 da 71 4f 5c c7 21 73 35...
2015-11-15 18:14:21      @20.98 ERR5d7a 10 15 f9 07 c5 0b 27 73 b3 a4...
2015-11-15 18:14:20      @19.98 ERR5d79 10 14 be f3 c6 c1 ae 03 c3 38...
2015-11-15 18:14:19      @18.98 ERR5d78 10 13 a7 4b 81 e4 7d a2 28 e3...
2015-11-15 18:14:18      @17.98 ERR5d77 10 12 86 bf 81 d9 22 a3 f3 46...
2015-11-15 18:14:17      @16.98 ERR5d76 10 11 e4 b1 12 31 3d 46 fc f1...
2015-11-15 18:14:16      @15.98 ERR5d75 10 10 26 f1 3b 0b 1f da 16 16...
2015-11-15 18:14:08      @08.98 ERR5d73 10 09 3a 40 1c a4 3b 91 ab 42...
2015-11-15 18:14:08      @07.98 ERR5d72 10 08 49 98 24 b6 15 09 e7 63...
2015-11-15 18:14:07      @06.98 ERR5d71 10 07 dd 38 86 f1 e3 81 f2 6c...
2015-11-15 18:14:06      @05.98 ERR5d70 10 06 1c 1d 26 97 5c 8f 9b 5c...
2015-11-15 18:14:04      @04.98 ERR5d6f 10 05 e2 0d db c8 cf e6 2a 5d...
2015-11-15 18:14:04      @03.98 ERR5d6e 10 04 3c 3a 87 2c f4 8d 31 38...
2015-11-15 18:14:03      @02.98 ERR5d6d 10 03 ee 7e 36 97 2d 26 38 36...
2015-11-15 18:14:02      @01.98 ERR5d6b 10 02 2e 2d 91 f2 3a 2b da d8...
2015-11-15 18:13:23      @22.98 ERR5d68 10 17 9c 26 e8 73 68 4d 21 c0...
2015-11-15 18:13:22      @21.98 ERR5d67 10 16 09 3b f2 b9 a3 2e 97 3e...
2015-11-15 18:13:21      @20.98 ERR5d66 10 15 e8 cc 29 56 99 08 8c 0c...
2015-11-15 18:13:20      @19.98 ERR5d65 10 14 99 2a 4b 4b f9 f1 ff 5b...
2015-11-15 18:13:19      @18.98 ERR5d64 10 13 6f c8 16 cc 55 a3 da 1b...
2015-11-15 18:13:18      @17.98 ERR5d63 10 12 8f 07 a7 72 ca bf ea 03...
2015-11-15 18:13:17      @16.98 ERR5d62 10 11 8f d4 3f f2 d2 45 2c 9b...
2015-11-15 18:13:15      @15.98 ERR5d61 10 10 2d 01 3d 85 75 52 28 6b...
2015-11-15 18:13:08      @08.98 ERR5d60 10 09 d2 93 31 b4 33 b7 ba b2...
2015-11-15 18:13:08      @07.98 ERR5d5f 10 08 43 de df dc a0 6d e0 b2...
2015-11-15 18:13:06      @06.98 ERR5d5e 10 07 38 2a 7b cf ec d1 28 5d...
2015-11-15 18:13:05      @05.98 ERR5d5d 10 06 8a 76 f9 6a 3f 93 e8 93...
2015-11-15 18:13:04      @04.98 ERR5d5c 10 05 9d 7d 57 c0 9a fe b6 00...
2015-11-15 18:13:03      @03.98 ERR5d5b 10 04 66 6a 62 54 68 e5 8c 13...
2015-11-15 18:13:02      @02.99 ERR5d59 10 03 09 3f 05 4c 2e 78 06 5e...
2015-11-15 18:13:01      @01.98 ERR5d57 10 02 f9 76 63 87 fd d6 63 ca...
2015-11-15 18:12:23      @22.99 ERR5d56 10 17 14 43 ad dd df aa c4 e0...
2015-11-15 18:12:22      @21.99 ERR5d55 10 16 a4 c4 6d 78 e9 61 16 91...
2015-11-15 18:12:21      @20.99 ERR5d54 10 15 9c eb 35 6e 07 3b 09 84...
2015-11-15 18:12:20      @19.99 ERR5d53 10 14 3d ce f2 50 e5 03 be 4a...
2015-11-15 18:12:19      @18.99 ERR5d52 10 13 a1 0c 6d 73 65 9a 02 1d...
2015-11-15 18:12:18      @17.99 ERR5d51 10 12 b2 2e 53 d6 2d b5 63 2e...
2015-11-15 18:12:17      @16.99 ERR5d50 10 11 7a 9a 35 7b c9 12 cf 91...
2015-11-15 18:12:16      @15.99 ERR5d4f 10 10 e1 6e d3 6e 92 e0 52 39...
2015-11-15 18:12:09      @08.99 ERR5d4e 10 09 e3 b2 22 9b cb 91 ee 09...
2015-11-15 18:12:08      @07.99 ERR5d4d 10 08 96 91 a2 f3 df b5 cc 28...
2015-11-15 18:12:07      @06.99 ERR5d4c 10 07 6f 22 2d 1f 1d 99 7c 28...
2015-11-15 18:12:06      @05.99 ERR5d4b 10 06 9a 25 0e 76 6e d1 58 0f...
2015-11-15 18:12:05      @04.99 ERR5d4a 10 05 53 e4 96 c4 39 2f aa c8...
2015-11-15 18:12:04      @03.99 ERR5d49 10 04 b3 90 d9 82 ce 3e 99 cc...
2015-11-15 18:12:03      @02.99 ERR5d48 10 03 7b 62 c7 8e 16 8f 20 5e...
2015-11-15 18:12:02      @01.99 ERR5d46 10 02 21 2d 2a 95 2a ce ff 8d...

Power consumption is too high

The CPU doesn;t go to powersave mode any more, because of this comit:

diff --git a/rfmsrc/common/rs232_485_hw.c b/rfmsrc/common/rs232_485_hw.c
index 5497192..3d1f4fa 100644
--- a/rfmsrc/common/rs232_485_hw.c
+++ b/rfmsrc/common/rs232_485_hw.c
@@ -161,7 +161,7 @@ void RS_Init(void)
                          UCSR0B = _BV(RXCIE0) | _BV(RXEN0);
                        #endif
         #else 
-            UCSR0B = _BV(RXCIE0) | _BV(RXEN0);
+            //UCSR0B = _BV(RXCIE0) | _BV(RXEN0);
             UCSR0C = (_BV(UCSZ00) | _BV(UCSZ01));     // Asynchron 8N1
         #endif
        #if !defined(_AVR_IOM16_H_) && !defined(_AVR_IOM32_H_) && !defined(_AVR_IOM328P_H_)

If I apply this patch, power consumption is down to around 40uA as opposed to 600uA with the RS232 enabled.

Support for RFM69

I am starting to RFMifying my HR20s and was running into the issue, that it has become more and more difficult to acquire RFM12-modules directly in Asia, as the manufacturer has ceased production of them...

The new go-to RFM seems to be the RFM69 - the cw-variant is even the same size as the RFM12.

Unfortunately, they are not a drop-in-replacement - as far as I was able to see, they need at least a different initialization-sequence. But properly initialized, they can even co-exists and communicate with RFM12-devices.

Therefore I wanted to inquire if there are any plans on adding support for RFM69-radios through a compile-switch. As I do not have a lot experience with wireless radios, I don't think that I'd be able to port the necessary changes myself.

However, if someone else would like to do it, I am more than happy to provide a RFM69-module for appropriate testing.

Display is not updating when changing modes

If I change via RS232 with M00 and M01 the display is updated from:
-> Manual Mode to Auto after approx. 1 minute
-> Auto Mode to Manual mode sometime after several minutes but sometimes not at all

I add a display update to com.c. I am not sure if thats the best solution (I don't speak C!)

        case 'M':
            if (COM_hex_parse(1*2)!='\0') { break; }
            CTL_change_mode(com_hex[0]);
            COM_print_debug(1);
            display_task = DISP_TASK_CLEAR | DISP_TASK_UPDATE;
            break;

Doesn't compile on newer gcc versions

In this post, "MM" suggests that gcc 4.7 messes up the EEPROM ordering. In this post, he offers the following fix:

Ok, this fixes the build with gcc > 4.3

Index: OpenHR20/Makefile
===================================================================
--- OpenHR20/Makefile   (revision 368)
+++ OpenHR20/Makefile   (working copy)
@@ -174,6 +174,7 @@
 CFLAGS += -funsigned-bitfields
 CFLAGS += -fpack-struct
 CFLAGS += -fshort-enums
+CFLAGS += -fno-toplevel-reorder
 CFLAGS += -Wall
 CFLAGS += -Wstrict-prototypes
 #CFLAGS += -mshort-calls

Newer gcc reorders eeprom variables

The layout in the eeprom get's changed when compiling with with newer gcc version (5.4.0).
It seems that -fno-toplevel-reorder doesn't work anymore. When searching the issue in the net, it is suggested to place the config in one struct.
Are there any other options?

old:
0000  00 00 00 14 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0010  ff 0f ff 0f 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0020  ff 0f ff 0f 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0030  ff 0f ff 0f 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0040  ff 0f ff 0f 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0050  ff 0f ff 0f 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0060  ff 0f ff 0f 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0070  ff 0f ff 0f 1c 22 3c 10  ff 0f ff 0f ff 0f ff 0f  |....."<.........|
0080  ff 0f ff 0f ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00c0  0e 0e 00 0f 1e 0a 0a 3c  24 22 0a 3c 2a 2a 0a 3c  |.....  <$" <** <|
00d0  2c 30 0a 3c 00 21 00 ff  10 08 00 ff 20 20 00 ff  |,0 <.!......  ..|
00e0  00 28 00 7f 01 1e 00 ff  30 30 04 ff 1a 1e 00 64  |.(......00.....d|
00f0  5c 2d 00 64 64 50 00 64  40 40 00 7f 20 20 20 ff  |\-.ddP.d@@..   .|
0100  fa fa 32 ff 64 64 01 ff  19 19 01 ff 4e 4e 05 ff  |..2.dd......NN..|
0110  6e 82 6e fa 96 96 6e fa  b8 b8 0a ff 32 32 0a c8  |n.n...n... .22 .|
0120  0a 0a 01 40 ff ff 00 ff  ff ff 00 ff 27 27 00 ff  |  .@........''..|
0130  2d 2d 10 ff 39 39 10 ff  4b 4b 10 ff 4d 4d 10 ff  |--..99..KK..MM..|
0140  41 41 10 ff 3d 3d 10 ff  18 00 00 7b 7a 78 50 a0  |AA..==.....{zxP.|
0150  73 64 50 a0 00 01 00 01  ff 32 07 ff ff 32 07 ff  |sdP......2...2..|
0160  01 08 01 20 01 08 01 20  0a 5a 02 ff 1a 1c 00 1d  |... ...  Z......|
0170  01 01 00 ff 23 23 00 ff  45 45 00 ff 67 67 00 ff  |....##..EE..gg..|
0180  89 89 00 ff ab ab 00 ff  cd cd 00 ff ef ef 00 ff  |................|
0190  00 00 00 ff 01 00 00 01  f3 00 00 ff ff ff ff ff  |................|
new:
0000  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0010  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0020  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0030  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0040  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0050  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0060  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0070  a4 21 1c 12 c0 23 ec 14  ff 2f ff 1f ff 2f ff 1f  |.!...#.../.../..|
0080  14 00 00 00 ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0090  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00a0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00b0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00c0  0e 0e 00 0f 0a 0a 0a 3c  22 22 0a 3c 2a 2a 0a 3c  |....   <"" <** <|
00d0  30 30 0a 3c 21 21 00 ff  08 08 00 ff 20 20 00 ff  |00 <!!......  ..|
00e0  28 28 00 7f 1e 1e 00 ff  30 30 04 ff 1e 1e 00 64  |((......00.....d|
00f0  2d 2d 00 64 50 50 00 64  40 40 00 7f 20 20 20 ff  |--.dPP.d@@..   .|
0100  fa fa 32 ff 64 64 01 ff  19 19 01 ff 4e 4e 05 ff  |..2.dd......NN..|
0110  82 82 6e fa 96 96 6e fa  b8 b8 0a ff 32 32 0a c8  |..n...n... .22 .|
0120  0a 0a 01 40 ff ff 00 ff  ff ff 00 ff 27 27 00 ff  |  .@........''..|
0130  2d 2d 10 ff 39 39 10 ff  4b 4b 10 ff 4d 4d 10 ff  |--..99..KK..MM..|
0140  41 41 10 ff 3d 3d 10 ff  00 00 00 7b 78 78 50 a0  |AA..==.....{xxP.|
0150  64 64 50 a0 01 01 00 01  32 32 07 ff 32 32 07 ff  |ddP.....22..22..|
0160  08 08 01 20 08 08 01 20  5a 5a 02 ff 1c 1c 00 1d  |... ... ZZ......|
0170  01 01 00 ff 23 23 00 ff  45 45 00 ff 67 67 00 ff  |....##..EE..gg..|
0180  89 89 00 ff ab ab 00 ff  cd cd 00 ff ef ef 00 ff  |................|
0190  00 00 00 ff 00 00 00 01  00 00 00 ff ff ff ff ff  |................|

Windoze guide?

Hi

i'm new here but for a heating control project i was told that the hr20 supports serial commands so i thought that would be great since i want to make a combined roller blind control and heating control

each window will have a pi that can control a stepper that runs the blind up and down, and its the "norm" in denmark to place radiators under the window so the pi will be close by anyway

now being used to windows has a drawback for me, what gui based tool do i use to compile and flash the code to the hr20? i have only seen linux based guides so far

i assume i could maybe use a pi to do it, but not sure
and i also need to get a jtag programmer, so far i have found this one
https://www.ebay.co.uk/itm/Altera-Mini-Usb-Blaster-Cable-For-CPLD-FPGA-NIOS-JTAG-Altera-Programmer-OD/264447616203?hash=item3d924e64cb:g:jLcAAOSwmLlX3WK2

any help is mostly welcome but its not a rush

the rf receiver doesn't get turned off after a missed sync packet

I'm researching why I seem to get a bad battery life on my OpenHR20 rfm12b equiped valves.

I built a small attiny85 based logger, that measures the current consumption of a valve around 150 times per second and starts to measure the time when the current goes above 1mA for more then 2 seconds.
The first column is the timestamp when the current dropped below 1mA again.
The second column is the duration in seconds over which the current was higher than 1mA
The third are uAh consumed during that time.
The fourth is the total time of the logger running.
The fifth are the mAh consumed while the logger was running.
The sixth is the estimated capacity used per year.

This log is from a valve running on my desk nextto the master in very a good rf environment.

usb_tiny85$ sudo ./logger
2015-10-06 18:08:28.2210 0.180 s 0.602 uAh total: 1.37 h 0.035 mAh 223.611 mAh/a
2015-10-06 20:07:30.0409 30.060 s 91.693 uAh total: 3.36 h 0.176 mAh 459.981 mAh/a
2015-10-06 20:26:30.0410 30.060 s 91.717 uAh total: 3.67 h 0.276 mAh 657.384 mAh/a
2015-10-07 03:43:00.0409 30.060 s 91.685 uAh total: 10.95 h 0.551 mAh 440.752 mAh/a
2015-10-07 07:28:00.1005 30.120 s 91.737 uAh total: 14.70 h 0.736 mAh 438.927 mAh/a
2015-10-07 16:32:28.1009 58.120 s 177.382 uAh total: 23.77 h 1.144 mAh 421.415 mAh/a
2015-10-07 17:35:00.0407 30.060 s 91.710 uAh total: 24.82 h 1.261 mAh 445.208 mAh/a
2015-10-07 21:24:00.1007 30.119 s 91.745 uAh total: 28.63 h 1.449 mAh 443.218 mAh/a
2015-10-07 21:36:28.1612 28.180 s 85.996 uAh total: 28.84 h 1.539 mAh 467.609 mAh/a
2015-10-07 21:37:28.1007 58.119 s 177.343 uAh total: 28.86 h 1.717 mAh 521.176 mAh/a
2015-10-08 01:25:00.0407 30.060 s 91.758 uAh total: 32.65 h 1.904 mAh 510.875 mAh/a
2015-10-08 05:03:00.0409 30.060 s 91.637 uAh total: 36.28 h 2.087 mAh 503.941 mAh/a
2015-10-08 13:47:00.0409 30.059 s 91.693 uAh total: 45.02 h 2.400 mAh 467.038 mAh/a
2015-10-08 14:53:30.0409 30.060 s 91.656 uAh total: 46.12 h 2.519 mAh 478.448 mAh/a
2015-10-08 16:57:55.4208 2 / 160 0.105 mA 48.20 h 2.571 mAh 467.296 mAh/a

I'd be glad on any hints on where to investigate further.

Problem with COM_RS232 enabled

Hi,

I had some problems with the serial interface (T, G, S... commands) and found a bug in COM_getchar(). The variable COM_requests is decreased for every single time an element is taken from the buffer, but it should only be decreased when c == '\n', like so:

    rx_buff_out%=RX_BUFF_SIZE;
    if (c == '\n') {
        COM_requests--;
    }
} else {

Cheers!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.