Giter Club home page Giter Club logo

esp8266_relay_board's Introduction

#FOTA Update Version - Requires NONOS-SDK 3.0.6 AND 1MB flash minimum.

-- To compile, you will need to install the ESP8266 dev toolchain as described here:

https://docs.espressif.com/projects/esp8266-rtos-sdk/en/latest/get-started/index.html#setup-toolchain

Or you can use the precompiled firmware in ./firmware directory which should match the HEAD of this branch.

--

So you want OTA on your 3-CH relay board, huh ? Bad news is you need 1Mb flash and to my knowledge, all of the 3-CH boards came with 512Kb.

Two choices:

  1. Desolder and solder a new flash chip (not too hard, but great care required) https://www.youtube.com/watch?v=7Q6ABad7U6o
  2. Desolder and solder a new ESP-03 module (most new one come with 1MB flash) Again, great care required not to damage the PCB tracks

Personlly, I think it's easier to desolder the flash chip and replace. It looks daunting, and if you fail you'll have a dead ESP-03. At this stage, your option is then to replace the ESP-03 itself with a 1MB variant (ebay is full of them).

To build, you'll need to use the command line Makefile and have all the toolchains installed (make, XTENSA, SDK, python, esptool.py etc). Use command line make to build, PlatformIO does not have this capability or up to date libraries at present. The build works for me on a Macbook (intel) running Catalina (10.15.7). I assume it will run fine on Linux also.

  1. Edit the Makefile and set the paths to the SDK and XTENSA compiler; set the FLASH_SIZE for your board
  2. Edit burn_boot.sh and burn_webpages.sh and set the path to ESPTOOL for your environment
  3. make clean
  4. make
  5. ./burn_boot.sh

Note, as per standard approach, only boot.bin and user1.bin are burnt to flash. user2.bin is burnt as a OTA upgrade.

Uses the new SDK partition_table_t struct and should autoconfigure as per the Makefile. Only tested on 1Mb flash; will not work on 512Kb for sure, however larger flash size should work (as supported by ESP8266 chip itself)

To upgrade firmware, visit the About page of the web interface and follow the instructions. You will need to upload either user1.bin or user2.bin (found in the firmware directory after compilation) as directed. Alternatively, wiflash (thanks esp-link project) is included to allow command line firmware push as follows: sh wiflash ./firmware/user1.bin ./firmware/user2.bin

Huge thanks to the https://github.com/jeelabs/esp-link project without whom, I would have never figure out how to do this.

#Three Channel WiFi Relay/Thermostat Board

The Three Channel WiFi Relay/Thermostat Board is a WiFi connected multi-purpose relay board based on the ESP8266 SoC, original designed by Martin Harizanov and sold by Open Energy Monitor Store in the UK

This fork of the code is actively maintained (2023), builds cleanly and has been rebased against NONOS-SDK 3.0.6. Note, this does NOT build in platformIO (PIO does not create user1.bin/user2.bin, and the NONOS-SDK and xtensa frameworks are very outdated). You can still use visual studio code, and tell it's build configurations to use native make - this allows build & FOTA from within Visual Code at the press of a button (apple shift B on my mac -chose the build option and watch it build as you would with PIO) See the file .vscode/tasks.json for how to do this. You will need the NONOS-SDK 8266 build framework installed to build and xtensa as described above under installing the build toolchains.

Various enhancements have been made:

###Enhancements to Martin's code

  • Full support for MQTT thermostat source
  • Enhanced MQTT reporting (state, DS18B20 JSON)
  • Avoid thermostat cycling
  • New Config items for MQTT thermostat timeout & thermostat cycling
  • Display of a bad or stale temperature readings highlighted in thermostat UI
  • Fix bug where thermostat relay off time is updated if it is already off
  • Change thermostat to work in tenths of a degree, not hundredths (direct compatibility with emonTh + emonGLCD)
  • Publish all ds18b20 sensors to MQTT by device-id
  • Choose which relays associate to each thermostat
  • FOTA Upgrade via webpage upload (thank you ESP-LINK project for the code)
  • Thermostat timeout for all sources implemented
  • Move all thermostat config to its own page in the Web GUI
  • ESPFS webpage upload now available through the Web GUI
  • Tidy up about.tpl page and only show firmware upgrade options when flash_map > 2 (over 512Kb)
  • Disable URLs for flashing firmware if flash_map < 2 (512Kb board)
  • Supports DST for Europe and North America (thanks Martin Harizanov for the code template)
  • Correct relay active for thermostat indicated in MQTT and JSON feeds (instead of relay1 default).
  • CurrentSetPoint published in state JSONs
  • Number of relays is now configurable via UI - if relay is not configured, it cannot be actuated via any means. This means code should work on 1-Relay boards and have correct UI and logic
  • Relays configured as thermostat controlled cannot be actuated via any other means (webpages, IO calls, MQTT)
  • Main menu updated
  • UI overview page completed to show most things and available on main menu (need to do ds18B20 sensors)
  • Thermostat colour map gradients configurable from web UI
  • Display all DS18B20 & DHT22 sensor values on new UI overview page
  • Tidy up serial interface - add help and validation of inputs
  • Add serial userJSON input - JSON can be submitted via serial, is published to MQTT and thermostat.cgi?state to allow easy customisation of webpages to support random serial devices
  • Add manual override mode to thermostat, if setpoint is adjusted while in scheduled mode, go into override mode; setpoint will reset to the next schedule temperature when it comes around
  • Add syslog logging feature for thermostat events
  • Thermostat Zone name configurable and thermostat.html page title reflects zone name (useful for multiple thermostats)
  • Able to download full week thermostat schedule in JSON format, upload one day at a time

.

Firmware update

To change firmware, set the programming switch to “PGM” position and attach 3.3V FTDI cable with GND (black wire) towards the USB plug. I find any of the cheap ESP programming USB plugs work well. JeeLabs USBBUB-II was not reliable. YMMV. Also see the (https://github.com/esp8266/esp8266-wiki/wiki/Uploading) ESP8266 WiKi for more details on uploading code.

[image]

Do not forget to flip back the PGM switch to the right side when done, or the code won’t start and the module will be stuck on bootloader mode.

You will need esptool.py installed. Precompiled firmware images are in the firmware directory. Use the burn_all.sh and burn_webpages.sh scripts to write firmware to the device. Modify the burn*.sh files appropriately to set paths for you USB port and path to esptool.py.

Note, the first time you do this all config will be LOST and you need to set the device up again from scratch (you need to join the devices WIFI AP and connect 192.168.4.1 in a browser).

If you are building and flashing using PIO, you still need to run the burn_webpages.sh script to deploy the webpages to the device.

--Original Readme.MD follows--

###Highlights

  • Option for on-board power supply
  • Up to three high quality 10A relays
  • Powered by the WiFi ESP8266 SoC module
  • HTTP API to control the relays
  • MQTT support
  • NTP for network time
  • HTTP daemon settings, including security/authentication setup
  • HTTP UI for configuration and control
  • Thermostat function with weekly scheduling
  • Manual relay control
  • Broadcast using HTTP GET to services like ThingSpeak and emonCMS
  • Integration with ThingSpeak for charting/analytics visualization
  • Temperature sensor support
  • DS18B20
  • DHT22

NOTE: The board connects to and controls high voltage, knowledge and care is required to handle it See more at the Three Channel WiFi Relay/Thermostat Board WiKi

#Author Martin Harizanov

#License This project is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

License

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

esp8266_relay_board's People

Contributors

alandpearson avatar mharizanov avatar surovtsev 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

esp8266_relay_board's Issues

Add new functionality: Digital input (button), published to MQTT

I bought a device through openenergymonitor. And it's very fine :), thanks and congratulation for it.
However, that would be great, if a falling or rising edge interrupt would be reported to MQTT as OFF/ON state.
If I see right, then the GPIO14 seems to be usable for this. (GPIO pulled up, a magnetic switch or a button closes it to GND)

To tell the truth, I would not use it as a thermostat, but as a garage door (and lighting) controller, and since the door has 4 commanding options, it would be necessary to detect the open/close state...
When somebody opens the door, often happen, that it remains open. A nodeRED instance would be used to detect the opening event, and after a period (and if other conditions apply) the nodeRED would use the 2. thermostat-relay to close the door.

Please let me know, can you implement such a functionality?

thanks,
Norbert

Thingspeak http broadcast resets relay

If I enable the http broadcast, the relay/leds will reset when a call to thingspeak is being made.
I have LEDS on the esp8266 outputs at the moment to easily spot this.
Obviously if I set latching to on it will reset to the original state.
If I turn http broadcast off (and restart), the relay state does not change ie - it doesn't reset.

http://harizanov.com is down

ping harizanov.com

Обмен пакетами с harizanov.com [195.191.148.125] с 32 байтами данных:
Превышен интервал ожидания для запроса.
Превышен интервал ожидания для запроса.
Превышен интервал ожидания для запроса.
Превышен интервал ожидания для запроса.

Статистика Ping для 195.191.148.125:
Пакетов: отправлено = 4, получено = 0, потеряно = 4
(100% потерь)

FYI

Would it be possible to port this

This looks great would it be possible to port this to a Sonoff basic/TH device.

This is now a very cheap sub £4 ESP8266 based board (not worth building one from scratch) with a single relay, and GPIO headers for thermostats such as AM2301.

oled display

Hi, I tested firmware from zip file, working great, Is this bin firmware contain oled support? where is connected sda, scl? display address? Thermostat working only with relay1? this absolute best project on esp8266.
Maybe you can display on oled, ip address, desired temperature, wifi status, signal strengh ... selectable from web ui, this oled display have great resolution and with small font it can display much more. Great job!

Compiling on Linux

After pulling a fresh clone from github , the mkespfsimage binary does not exist and needs to be compiled. However the firmware/Makefile results in errors:

> cd firmware
> make
CC driver/i2c.c
CC driver/i2c_oled.c
.
.
/bin/sh: 1: ../mkespfsimage/mkespfsimage: not found

A quick way to fix this is to manually compile mkespfsimage

cd mkespfsimage
make
cd ..
make

It would be best if this was fixed in the firmware/Makefile.
The following are the patches I made to fix the problem.
It also cleans up the use of _$(FW_FILE_3)_ and adds a _distclean_ target.

diff -u Makefile_orig Makefile
--- Makefile_orig   2015-03-15 11:55:51.000000000 -0400
+++ Makefile    2015-03-21 15:32:14.109171100 -0400
@@ -125,7 +125,7 @@

 .PHONY: all checkdirs clean

-all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)
+all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2) $(FW_FILE_3)

 $(FW_FILE_1): $(TARGET_OUT) firmware
    $(vecho) "FW $@"
@@ -135,6 +135,18 @@
    $(vecho) "FW $@"
    $(Q) $(ESPTOOL) -eo $(TARGET_OUT) $(FW_FILE_2_ARGS)

+$(FW_FILE_3): html/ html/config/ html/config/wifi/ html/control/ mkespfsimage/mkespfsimage
+   $(vecho) "MKEFSIMAGE $@"
+ifeq ($(GZIP_COMPRESSION),"yes")
+   $(Q) rm -rf html_compressed;
+   $(Q) cp -r html html_compressed;
+   $(Q) cd html_compressed; find . -type f -regex ".*/.*\.\(html\|css\|js\)" -exec sh -c "gzip -n {}; mv {}.gz {}" \;; cd ..;
+   $(Q) cd html_compressed; find  | ../mkespfsimage/mkespfsimage > ../$(FW_FILE_3); cd ..;
+else
+   $(Q) cd html; find | ../mkespfsimage/mkespfsimage > ../$(FW_FILE_3); cd ..
+endif
+   $(Q) if [ $$(stat -c '%s' $(FW_FILE_3)) -gt $$(( 0x2E000 )) ]; then echo $(FW_FILE_3)" too big!"; false; fi
+
 $(TARGET_OUT): $(APP_AR)
    $(vecho) "LD $@"
    $(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@
@@ -143,18 +155,6 @@
    $(vecho) "AR $@"
    $(Q) $(AR) cru $@ $^

-ifeq ($(GZIP_COMPRESSION),"yes")
-   $(Q) rm -rf html_compressed;
-   $(Q) cp -r html html_compressed;
-   $(Q) cd html_compressed; find . -type f -regex ".*/.*\.\(html\|css\|js\)" -exec sh -c "gzip -n {}; mv {}.gz {}" \;; cd ..;
-   $(Q) cd html_compressed; find  | ../mkespfsimage/mkespfsimage > ../webpages.espfs; cd ..;
-else
-   $(Q) cd html; find | ../mkespfsimage/mkespfsimage > ../webpages.espfs; cd ..
-endif
-
-   if [ $$(stat -c '%s' webpages.espfs) -gt $$(( 0x2E000 )) ]; then echo "webpages.espfs too big!"; false; fi
-   $(ESPTOOL) -cp $(ESPPORT) -cb $(ESPBAUD) -ca 0x12000 -cf webpages.espfs -v
-   
 checkdirs: $(BUILD_DIR) $(FW_BASE)

 $(BUILD_DIR):
@@ -169,22 +169,12 @@
    $(Q) sleep $(ESPDELAY) || true
    $(Q) $(ESPTOOL) -cp $(ESPPORT) -cb $(ESPBAUD) -ca 0x40000 -cf firmware/0x40000.bin -v

-webpages.espfs: html/ html/wifi/ mkespfsimage/mkespfsimage
-ifeq ($(GZIP_COMPRESSION),"yes")
-   $(Q) rm -rf html_compressed;
-   $(Q) cp -r html html_compressed;
-   $(Q) cd html_compressed; find . -type f -regex ".*/.*\.\(html\|css\|js\)" -exec sh -c "gzip -n {}; mv {}.gz {}" \;; cd ..;
-   $(Q) cd html_compressed; find  | ../mkespfsimage/mkespfsimage > ../webpages.espfs; cd ..;
-else
-   $(Q) cd html; find | ../mkespfsimage/mkespfsimage > ../webpages.espfs; cd ..
-endif
-
 mkespfsimage/mkespfsimage: mkespfsimage/
    make -C mkespfsimage

-htmlflash: webpages.espfs
-   if [ $$(stat -c '%s' webpages.espfs) -gt $$(( 0x2E000 )) ]; then echo "webpages.espfs too big!"; false; fi
-   $(ESPTOOL) -cp $(ESPPORT) -cb $(ESPBAUD) -ca 0x12000 -cf webpages.espfs -v
+htmlflash: $(FW_FILE_3)
+   if [ $$(stat -c '%s' $(FW_FILE_3)) -gt $$(( 0x2E000 )) ]; then echo $(FW_FILE_3)" too big!"; false; fi
+   $(ESPTOOL) -cp $(ESPPORT) -cb $(ESPBAUD) -ca 0x12000 -cf $(FW_FILE_3) -v

 clean:
    $(Q) rm -f $(APP_AR)
@@ -200,6 +190,9 @@
    $(Q) rm -f $(FW_FILE_3)

    $(Q) rm -rf $(FW_BASE)
+   
+distclean: clean
+   $(Q) make -C mkespfsimage clean


 $(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))

KRACK Vulnerability

Hello Martin,

any hint about what has to be changed in order to patch the KRACK vulnerability?

Thanks!

TLS and certificate

While waiting for my first ESP8266 Wifi Relay to be delivered by OpenEnergyMonitor, I'm not able to understand from the documentation how it would be possible to upload a ca.crt (certificate) for MQTT TLS Authentication. Any hint?

Connection problem

Hi, I try compile this under windows CHERTS DEVKIT, all done OK but when I flash binaries, no wifi or no conenction, I no not know where is problem, I try hold GPIO0, smetimes I have signal, sometime not, I have used several esp modules. Can you please share binaries for test if is problem with compilation or where.

Compiled Version

Hello
Does anyone have compiled version of this firmware?
I'm big noob in code dev and have a lot problem with compile this.

Regards

error on compiling

in the new broadcastd.c line 87
struct sensor_reading* result = read_ds18b20(0);

should it be:
struct sensor_reading* result = read_ds18b20();

Sorry - I dont know git enough to do a pull
Tony

muliple ds18b20

your board can read multiple ds18b20, is possible store values of more sensors to thingspeak
etc indoor, outdoor or radiator temperature ?

thingspeak RO key

RO api key is not saved.
Can you describe how to configure thingspeak, no valuses stored or zero only

Use multiple Digital sensors

Should allow for more sensors, and the option to select wich one like dt11, for inside, outside temp, or a ligth sensor

MQTT documentation

Hi,

I'm struggling to find documentation about the MQTT possibilities. What commands can be given to the thermostat using MQTT?

For example:

  1. Is it possible to change the set temperature on the thermostat?
  2. Is it possible to change the schedule-mode to manual-mode and back using MQTT?

Can you tell me more about this?

Kind regards,

Roy

compiling issue

thanks in advance ...
esp8266@esp8266-VirtualBox:/ESP8266_Relay_Board-master/1ch_relay$ make
CC driver/i2c.c
In file included from driver/i2c.c:22:0:
/opt/ESP8266_NONOS_SDK/include/osapi.h:45:15: error: conflicting types for 'os_random'
unsigned long os_random(void);
^
In file included from driver/i2c.c:20:0:
include/espmissingincludes.h:46:5: note: previous declaration of 'os_random' was here
int os_random();
^
In file included from /opt/ESP8266_NONOS_SDK/include/ets_sys.h:12:0,
from include/espmissingincludes.h:4,
from driver/i2c.c:20:
driver/i2c.c: In function 'i2c_init':
/opt/ESP8266_NONOS_SDK/include/eagle_soc.h:249:38: error: suggest parentheses around arithmetic in operand of '|' [-Werror=parentheses]
& (
(PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S))
^
/opt/ESP8266_NONOS_SDK/include/eagle_soc.h:50:98: note: in definition of macro 'WRITE_PERI_REG'
#define WRITE_PERI_REG(addr, val) (*((volatile uint32_t )ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val)
^
driver/i2c.c:64:5: note: in expansion of macro 'PIN_FUNC_SELECT'
PIN_FUNC_SELECT(I2C_SDA_MUX, I2C_SDA_FUNC);
^
/opt/ESP8266_NONOS_SDK/include/eagle_soc.h:249:38: error: suggest parentheses around arithmetic in operand of '|' [-Werror=parentheses]
& (~(PERIPHS_IO_MUX_FUNC<<PERIPHS_IO_MUX_FUNC_S))
^
/opt/ESP8266_NONOS_SDK/include/eagle_soc.h:50:98: note: in definition of macro 'WRITE_PERI_REG'
#define WRITE_PERI_REG(addr, val) (
((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val)
^
driver/i2c.c:65:5: note: in expansion of macro 'PIN_FUNC_SELECT'
PIN_FUNC_SELECT(I2C_SCK_MUX, I2C_SCK_FUNC);
^
cc1: all warnings being treated as errors
make: *** [build/driver/i2c.o] Error 1
esp8266@esp8266-VirtualBox:~/ESP8266_Relay_Board-master/1ch_relay$

Compiling

This is stunningly similar to the work we've just about completed over the weekend! Except we're using node-red to provide time etc on the other hand you've done what looks like a cracking job on the scheduler.
Any change of making this so it will compile with Eclipse on Windows? OR provide a set of binaries so I can give this a go?

Add new functionality: push button to override temp

as subject say i can use the code as is, but i just miss an button to press that overrides the target temp to something else

goal is to control an electrical heating panel in a flat where an autism person lives.. the staff taking care of this person has a tendency to poke their fingers at the controls allready in the panels so i thought of replacing it with something else

i have allready made a bench setup with an pi and ds18b20 but the pi zero's are to expensive given that there are at least 5 panels to control and i dont want wires in between

an esp8266 nails it as the price is much lower... it just miss's the override button to raise/boost temp for an period of time

GMT Offset setting does not take effect immediately

In the NTP dialog, the GMT Offset setting does not take effect immediately.
It requires a reboot/restart to take effect

the following patch fixes the problem

> diff -u cgi.c_orig cgi.c
--- cgi.c_orig  2015-03-15 11:55:51.000000000 -0400
+++ cgi.c   2015-03-21 17:33:44.016871800 -0400
@@ -591,6 +591,7 @@
    len=httpdFindArg(connData->postBuff, "ntp-tz", buff, sizeof(buff));
    if (len>0) {
        sysCfg.ntp_tz=atoi(buff);       
+       sntp_tz=sysCfg.ntp_tz;
    }   

    CFG_Save();

crash after setup wifi key and ap

when ai flash i get the html page to config the wifi , after i choose the wifi network , it reboot and go in bootloop

load 0x40100000, len 1856, room 16
tail 0
chksum 0x63
load 0x3ffe8000, len 776, room 8
tail 0
chksum 0x02
load 0x3ffe8310, len 552, room 8
tail 0
chksum 0x79
csum 0x79

2nd boot version : 1.5
SPI Speed : 80MHz
SPI Mode : QIO
SPI Flash Size & Map: 16Mbit(1024KB+1024KB)
jump to run user1 @ 1000

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.