GithubHelp home page GithubHelp logo

marcelstoer / nodemcu-pyflasher Goto Github PK

View Code? Open in Web Editor NEW
1.4K 64.0 395.0 2.25 MB

Self-contained NodeMCU flasher with GUI based on esptool.py and wxPython.

License: MIT License

Python 99.93% Shell 0.05% Batchfile 0.02%
esptool nodemcu wxpython pyinstaller

nodemcu-pyflasher's Introduction

NodeMCU PyFlasher

License Github Releases PayPal Donation Twitter URL Facebook URL

Self-contained NodeMCU flasher with GUI based on esptool.py and wxPython.

Image of NodeMCU PyFlasher GUI

Installation

NodeMCU PyFlasher doesn't have to be installed, just double-click it and it'll start. Check the releases section for downloads for your platform. For every release there's at least a .exe file for Windows. Starting from 3.0 there's also a .dmg for macOS.

Status

Scan the list of open issues for bugs and pending features.

Note

This is my first Python project. If you have constructive feedback as for how to improve the code please do reach out to me.

Getting help

In the unlikely event that you're stuck with this simple tool the best way to get help is to turn to the "Tools and IDE" subforum on esp8266.com.

Donationware

All open-source development by the author is donationware. Show your love and support for open-source development by donating to the good cause through PayPal.

PayPal Donations

Build it yourself

If you want to build this application yourself you need to:

  • Install Python 3.x and Pip (it comes with Python if installed from python.org).
  • Create a virtual environment with python -m venv venv
  • Activate the virtual environment with . venv/bin/activate (. venv/Scripts/activate if you are on Windows with Cygwin or Mingw)
  • Run pip install -r requirements.txt

A note on Linux: As described on the downloads section of wxPython, wheels for Linux are complicated and may require you to run something like this to install wxPython correctly:

# Assuming you are running it on Ubuntu 18.04 LTS with GTK3
pip install -U \
    -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04 \
    wxPython

Why this project exists

Motivation

This addresses an issue the NodeMCU community touched on several times in the past, most recently at #1500 (comment).

I stated that based on my experience doing NodeMCU user support it should be a lot simpler to flash NodeMCU for Windows users.

  • A number of flashing tools are available but only two are actively maintained: esptool-ck and esptool.py. Only one is endorsed by Espressif: esptool.py (they hired the developer(s)).
  • 70% of the users of my nodemcu-build.com service are on Windows.
  • BUT Windows doesn't come with Python installed - which is required for esptool.py.
  • BUT Windows users in general are more reluctant to use the CLI than Linux/Mac users - which is required for esptool.py.

To conclude: this is not a comfortable situation for NodeMCU's largest user group.

The plan

For quite a while I planned to write a self-contained GUI tool which would use esptool.py in the background. It should primarily target Windows users but since I'm on Mac it should be cross-platform. Even though I had never used Python before I felt confident to pull this off.

Implementation

  • Uses the cross-platform wxPython GUI framework. I also tried PyForms/PyQt4 but settled for wxPython.
  • Requires absolutely minimal user input.
  • The esptool.py "console" output is redirected to text control on the GUI.
  • Uses PyInstaller to create self-contained executable for Windows and Mac. The packaged app can run standalone i.e. without installing itself, a Python interpreter or any modules.

License

MIT © Marcel Stör

nodemcu-pyflasher's People

Contributors

marcelstoer avatar murilopolese avatar utkarshsethi 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  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

nodemcu-pyflasher's Issues

How to connect

I've bought multiple NodeMCU's and the instalment of the first one went flawlessly, but when I tried to help a friend it wasn't able to detect a port with something attacted. I've tried it on multiple pc's but I could get it to work. Is there something I could do?

New version?

Hello, I would like to know if there is any date expected to launch the program for MAC OS with the new changes. Thank you!!

OSX version is not showing interface

both 3.0 and 4.0 are not showing interface after starting program.
Icon appears shortly in doc and then disappears again.

No failure messages.

running Sierra 10.12.6

excuse me.. overlooked IOS version

Add validation

Ensure that both com port and firmware file are selected before the user triggers the flash action. Disable button until then?

Fatal Error - Failed to open script nodemenu-pyflasher

Error occured so I deleted the dist\NodeMCU-PyFlasher.exe and tried again as below. Tried running exe as admin, no change.

G:\Downloads\nodemcu-pyflasher-master>build

G:\Downloads\nodemcu-pyflasher-master>pyinstaller --log-level=DEBUG --noconfirm build-on-win.spec
182 INFO: PyInstaller: 3.2.1
182 INFO: Python: 3.5.2
183 INFO: Platform: Windows-10-10.0.14393-SP0
184 DEBUG: Testing for UPX ...
186 INFO: UPX is not available.
188 DEBUG: script: nodemcu-pyflasher.py
188 INFO: Extending PYTHONPATH with paths
['G:\Downloads\nodemcu-pyflasher-master']
189 INFO: checking Analysis
215 INFO: Appending 'datas' from .spec
221 INFO: checking PYZ
248 INFO: checking PKG
250 INFO: Building because toc changed
251 INFO: Building PKG (CArchive) out00-PKG.pkg
392 DEBUG: Compiling c:\users\geoff\anaconda3\lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py
392 DEBUG: Compiling c:\users\geoff\anaconda3\lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py
395 DEBUG: Compiling G:\Downloads\nodemcu-pyflasher-master\nodemcu-pyflasher.py
396 DEBUG: Compiling G:\Downloads\nodemcu-pyflasher-master\nodemcu-pyflasher.py
2315 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
2326 INFO: Bootloader c:\users\geoff\anaconda3\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe
2327 INFO: checking EXE
2329 INFO: Rebuilding out00-EXE.toc because NodeMCU-PyFlasher.exe missing
2329 INFO: Building EXE from out00-EXE.toc
2358 INFO: SRCPATH [('images\icon-256.ico', None)]
2358 INFO: Updating icons from ['images\icon-256.ico'] to C:\Users\Geoff\AppData\Local\Temp\tmpevfm734m
2361 INFO: Writing RT_GROUP_ICON 0 resource with 20 bytes
2361 INFO: Writing RT_ICON 1 resource with 26144 bytes
2390 INFO: Appending archive to EXE G:\Downloads\nodemcu-pyflasher-master\dist\NodeMCU-PyFlasher.exe
2573 INFO: Building EXE from out00-EXE.toc completed successfully.

get memory size

would it be possible to add a Button to get memory size (or as much ifo about the chip)
before flashing?

--flash_size=detect
--port /dev/ttyUSB0 flash_id

for example?

Error after flashing an ESP32 based Lolin32 Lite: flash read err, 1000 ets_main.c 371

Hello,

I experiencing the following error after flashing an ESP32 based 4M flash LoLin32 Lite:

0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57
....

If I use the Arduino IDE (which I think also uses the esptool.py), then I can program anything on the board, it will work. Of course in C, but I would like to use Lua or MicroPython.

Could you suggest what am I doing wrong?

Thanks,

Not working on specific computer

Hi

Using my laptop (win10 64, com 9 recognized) trying to flash. the log shows only the 1st line of the "command:" and doesn't proceeds to the flashing operation. One line written only, no flashing. Tried any possible option including open as administrator, installing ftdi drivers... Nothing.

On another old and sluggish laptop, the tool is working just great.

I'd appreciate your assistance!

Error detecting flash size on ESP-01

I'm using the utility for long period with no issues on Wemos D1 modules, however there are some king of misbehavior with ESP-01 modules.
Form my latest test what I'm understanding is that the utility fails to detect correctly the flash size on the modules.

Here how the process goes.
Step one: Flash the module. (it detects 1MB of flash size)
1_success
The procedure completes with no errors and at this point I think that the module is flashed correctly.
But when I connect serial monitor there is no correct response from it. I getting the following:
`ets Jan 8 2013,rst cause:4, boot mode:(3,6)

wdt reset
load 0x40100000, len 27780, room 16
tail 4
chksum 0x57
load 0x3ffe8000, len 2440, room 4
tail 4
chksum 0xfa
load 0x3ffe8988, len 136, room 4
tail 4
chksum 0x62
csum 0x62
csum err
ets_main.c
`
Trying to flash with a new firmware file (I just thought that the 1st one was over sized) the utility detects a different flash size
2_unfinished
it never fisnished...

So after resetting the module and try to re-flash the things gone extremely wrong... it seems that the esp module was bricked permanently.
3_aftererror

Is there any specific solution fro flashing ESP-01 modules with this GREAT UTILITY?

mac build problem and solution: can't not build with wxpython 4.0.*

on mac, try to build, but can't, some function miss like:SplashScreen, SPLASH_CENTRE_ON_SCREEN , SPLASH_TIMEOUT, wx.ST_SIZEGRIP.

i fix this by modify the import path
from wx.adv import SplashScreen, SPLASH_CENTRE_ON_SCREEN , SPLASH_TIMEOUT
and
change wx.ST_SIZEGRIP to wx.STB_SIZEGRIP,

Support Flash Mode Dout

I would like to advertize your tool for my Tasmota project as it seems to be a single container executable.

To get rid of all kinds of issues regarding different hardware (ESP8266 vs ESP8285) I decided to only support Flash Mode Dout as it works fine on both chips and all Tasmota supported hardware.

Would you consider implementing the Dout option in your Gui?

can it be done via pip installation ?

hi, there is able to complete esptool & wxpython by uses python and the pip.
how about your great piece of software, this asking is because we are new to python and have no idea how to uses your tools to build the GUI under windows.
thanks.

macos high sierra crash after build

Hi, I build pyflasher, and generate the NodeMCU-PyFlasher.app file, but when I click it, it just crash. Not sure for the reason, maybe should check it out?

Stops connecting

Hello, im using a ESP8266 with an USB232 interface, at 9600bps:

Connecting....
Running Cesanta flasher stub...
Erasing flash (this may take a while)...
Erase took 2.4 seconds
Connecting...................

Lights onUSB232 stops blinking.
Bye

error run latest code at ubuntu

i run pyflasher before. After latest git pull i get error
python ./nodemcu-pyflasher.py Traceback (most recent call last): File "./nodemcu-pyflasher.py", line 3, in <module> import Main File "/home/johndoe/Programs/esp8266/nodemcu-pyflasher/Main.py", line 4, in <module> import wx.adv ImportError: No module named adv
lubuntu 14.04
python-wxversion 3.0.1.1+dfsg-2ubuntu14.04.1ppa1
python-wxgtk3.0-dev 3.0.1.1+dfsg-2ubuntu14.04.1ppa1
python-wxgtk2.8 2.8.12.1+dfsg-2ubuntu2
python-wxgtk3.0 3.0.1.1+dfsg-2ubuntu14.04.1ppa1
installed

Not Compiling on Mac 10.12.6

I downloaded and installed both wxPython and esptool.py by I am getting this error message

Traceback (most recent call last):
File "/Users/.../nodemcu-pyflasher-master/nodemcu-pyflasher.py", line 3, in
import Main
File "/Users/.../nodemcu-pyflasher-master/Main.py", line 347, in
class MySplashScreen(wx.SplashScreen):
AttributeError: 'module' object has no attribute 'SplashScreen'

WX error on build

I have pip install everything i can think of and i still get this error on my mac. I have python 2.7.10 and 3 and neither work

File "nodemcu-pyflasher.py", line 3, in
import Main
File "/Users/djmason9/Downloads/nodemcu-pyflasher-master/Main.py", line 3, in
import wx

Add support for ESP32

Add support for ESP32.
ESP32 support is added in esptool.py v2 (currently in beta)

Missing DLL when importing `wxPython`

After installing the dependencies on Windows 10 (MSEdge virtual box image) I get the following error trying to run the application:

$ python nodemcu-pyflasher.py
Traceback (most recent call last):
  File "nodemcu-pyflasher.py", line 3, in <module>
    import Main
  File "C:\Users\IEUser\Projects\nodemcu-pyflasher\Main.py", line 3, in <module>
    import wx
  File "C:\Users\IEUser\Projects\nodemcu-pyflasher\venv\lib\site-packages\wx\__init__.py", line 17, in <module>
    from wx.core import *
  File "C:\Users\IEUser\Projects\nodemcu-pyflasher\venv\lib\site-packages\wx\core.py", line 12, in <module>
    from ._core import *
ImportError: DLL load failed: The specified module could not be found.

I am not sure if this has anything to do with nodemcu-pyflasher itself but perhaps wxPython requires a specific version of the package, Python, pip, and maybe some setup on the host machine.

May or may not be related to #39 .

AttributeError: 'unicode' object has no attribute 'baudrate'

Hi, using version 3.0 I have this error.

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python27\lib\threading.py", line 801, in __bootstrap_inner
    self.run()
  File "C:\NodeMCU\nodemcu-pyflasher\Main.py", line 76, in run
    esp = ESPLoader.detect_chip(self._config.port, initial_baud)
  File "C:\NodeMCU\nodemcu-pyflasher\esptool.py", line 216, in detect_chip
    detect_port = ESPLoader(port, baud, trace_enabled=trace_enabled)
  File "C:\NodeMCU\nodemcu-pyflasher\esptool.py", line 195, in __init__
    self._set_port_baudrate(baud)
  File "C:\NodeMCU\nodemcu-pyflasher\esptool.py", line 200, in _set_port_baudrate
    self._port.baudrate = baud
AttributeError: 'unicode' object has no attribute 'baudrate'

Any suggestion please ?
Thanks

Report exception when serial port is busy

pyserial throws an exception when the com port is busy (e.g. because ESPlorer is attached to it in parallel) while esptool tries to communicate. Catch that exception and similar ones and display them in the console component.

Release COM port when flash process is finished

OS
Windows 7, Windows 10

NodeMCU-PyFlasher version
3.0

Description
When I upload the firmware I'm not able to use Esplorer until I close the flasher. It looks that COM port is still locked.

Expected behavior
COM port can be used by any other app as soon as Flasher finish his job - without closing it.

Feedback from the terminal window after Hard resetting.

I receive no feedback in the terminal window after the message "Hard resetting..." after flashing the firmware and clearing the flash (Windows 7). Serial set to 115200. I expected to see a message from the Nodemcu board: "Formatting the file system. Please wait..." or something. I simply wait for 2 to 3 minutes, so that this initial formatting has time to finish :) and then disconnect and reconnect the USB power to the Nodemcu board and everything is OK. Am I doing something wrong or is this common on Windows?

Is it actually erasing the whole flash mem in 2 seconds?

I'm programming a ESP-12E on a Win7 computer.
Your new Pyflasher V1.0.1 program looks like it might be easier to use than the
original NodeMCU Flasher - for windows computers.
But although it says that it has successfully flashed the memory, I have yet to
get any of the binaries I've flashed with it, to boot.

Here's the log it produces:

Connecting....
Running Cesanta flasher stub...
Erasing flash (this may take a while)...
Erase took 1.6 seconds
Connecting....
Auto-detected Flash size: 32m
Running Cesanta flasher stub...
Flash params set to 0x0040
Writing 450560 @ 0x0...
Wrote 450560 bytes at 0x0 in 39.2 seconds (91.9 kbit/s)...
Leaving...
Verifying just-written flash...
Flash params set to 0x0040
Verifying 0x6de18 (450072) bytes @ 0x00000000 in flash against D:\Downloads\ESP8266\Software\Firmware\V0.9.6\nodemcu_integer_0.9.6-dev_20150704.bin...
-- verify OK (digest matched)

Notice how it says it took only 1.6 seconds to erase the memory.
And that's true - that function skips through in only 2 seconds.

In the past I've only gotten my unit to boot after having FIRST flashed the full memory with so called "blank" files.
That is, those that have been programmed with FF in each byte of the 1MB section on memory.
So the 0x00000, 0x10000, 0x20000, and 0x30000 address sections all get set to FF in every byte.
In all of those cases it took at least 10 minutes to erase the 4MB of memory.
The binaries I've been trying to flash have not only been from the NodeMCU Custom Builds website, but the 0.9.6 version as well.

I've only been at this for 3 weeks, and it's been a pretty steep learning curve, so please forgive any
newbie assumptions I might make.
Regardless of if I select erase flash, or not, I haven't yet seen success with this version of this tool.
Although I do appreciate the effort.

Version 64x not running

I'm running the tool version 64x in windows 7.
Is not important, but I received a message error box from windows telling:

"Error loading Python DLL"
'c:\Users\myuser\AppData\Local\Temp_MEI39202\python35.dll'
LoadLibrary:

Ok, I checked the folder and the .dll is inside.

Running the 32bits version is ok for me.

Than you for your time
Janus

Requirements.txt / setup.py missing

Building this project is unnecessarily complex, since the standard python distutils is not used, and instead the build script just assumes everything installed (which means I have to guess and read the versions from README.md, etc).

Wouldn't it just be better to use the standard Python way of doing things (and publish releases on PyPi instead of custom builds)?

Since you are using an old version of wxPython, etc, the only realistic way of running AFAIK is under Virtualenv (since wx is Cocoa and does not run under e.g. Docker).

Are there directions?

Hi, just wondering are there directions for this application?

I am on windows 10, and used Git Bash to run the command ./build.sh which I'm guessing is what we are supposed to do.

However I got an error and I don't recognize it:

$ ./build.sh
105 INFO: PyInstaller: 3.2.1
105 INFO: Python: 3.5.3
105 INFO: Platform: Windows-10-10.0.15063-SP0
105 DEBUG: Testing for UPX ...
106 INFO: UPX is not available.
107 DEBUG: script: nodemcu-pyflasher.py
107 INFO: Extending PYTHONPATH with paths
['C:\\Users\\JP\\Desktop\\nodemcu-pyflasher-master']
107 INFO: checking Analysis
116 INFO: Appending 'datas' from .spec
118 INFO: checking PYZ
132 INFO: checking PKG
133 INFO: Building because toc changed
133 INFO: Building PKG (CArchive) out00-PKG.pkg
175 DEBUG: Compiling c:\python35\lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py
175 DEBUG: Compiling c:\python35\lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py
176 DEBUG: Compiling C:\Users\JP\Desktop\nodemcu-pyflasher-master\nodemcu-pyflasher.py
176 DEBUG: Compiling C:\Users\JP\Desktop\nodemcu-pyflasher-master\nodemcu-pyflasher.py
1558 INFO: Building PKG (CArchive) out00-PKG.pkg completed successfully.
1564 INFO: Bootloader c:\python35\lib\site-packages\PyInstaller\bootloader\Windows-64bit\runw.exe
1564 INFO: checking EXE
1564 INFO: Building EXE because out00-EXE.toc is non existent
1564 INFO: Building EXE from out00-EXE.toc
1586 INFO: SRCPATH [('images/icon-256.icns', None)]
1586 INFO: Updating icons from images/icon-256.icns to C:\Users\JP\AppData\Local\Temp\tmpl6b0n8y1
Traceback (most recent call last):
  File "c:\python35\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\python35\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Python35\Scripts\pyinstaller.exe\__main__.py", line 9, in <module>
  File "c:\python35\lib\site-packages\PyInstaller\__main__.py", line 90, in run
    run_build(pyi_config, spec_file, **vars(args))
  File "c:\python35\lib\site-packages\PyInstaller\__main__.py", line 46, in run_build
    PyInstaller.building.build_main.main(pyi_config, spec_file, **kwargs)
  File "c:\python35\lib\site-packages\PyInstaller\building\build_main.py", line 788, in main
    build(specfile, kw.get('distpath'), kw.get('workpath'), kw.get('clean_build'))
  File "c:\python35\lib\site-packages\PyInstaller\building\build_main.py", line 734, in build
    exec(text, spec_namespace)
  File "<string>", line 27, in <module>
  File "c:\python35\lib\site-packages\PyInstaller\building\api.py", line 411, in __init__
    self.__postinit__()
  File "c:\python35\lib\site-packages\PyInstaller\building\datastruct.py", line 161, in __postinit_
    self.assemble()
  File "c:\python35\lib\site-packages\PyInstaller\building\api.py", line 498, in assemble
    icon.CopyIcons(tmpnm, self.icon)
  File "c:\python35\lib\site-packages\PyInstaller\utils\win32\icon.py", line 172, in CopyIcons
    hsrc = win32api.LoadLibraryEx(srcpath, 0, LOAD_LIBRARY_AS_DATAFILE)
pywintypes.error: (193, 'LoadLibraryEx', '%1 is not a valid Win32 application.')

Thanks!

Display esptool.py command line

Tried the tool (windows 10) and it worked perfectly.
It would be nice if the command line used to start esptool.py would be displayed.

I stop working in linux

It worked very well but after upgrading my linux mint and python I could not make it work anymore. I suppose the problem is with versions of wxwindow and python, but I have not been able to solve it. So I will use esptool directly.
It hurts, because I liked a lot of pyflasher.

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.