Giter VIP home page Giter VIP logo

home-climate-control / dz Goto Github PK

View Code? Open in Web Editor NEW
57.0 10.0 6.0 19.42 MB

Home Climate Control Core: *the* Open Source multi-zone temperature and climate control system.

Home Page: http://homeclimatecontrol.com/

License: GNU General Public License v3.0

Java 82.98% Shell 0.05% HTML 16.97%
climate-control home-automation thermostat zoning raspberry-pi remote-control android java 1-wire xbee

dz's Introduction

Home Climate Control

Build Status Build Status Build Status SonarCloud

Create as many climates in your home as you never thought imaginable.
Control temperature, humidity and ventilation.
Do it on a schedule.
Have everything measured and recorded.
Do it from anywhere.


v4.2.0. is out

Documentation

Your best bet is to read the documentation that resides in the branch you're looking at, at ./docs/index.md If in doubt, don't hesitate to post a message to our user forum, help will come fast.

Next Steps

dz's People

Contributors

climategadgets avatar dependabot[bot] avatar marcass 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dz's Issues

Find a way to not repaint the console if it is not visible

Currently, repaint() is called on Swing Console even if the console is not visible (obscured by other windows, or is on a disconnected X-Window or VNC screen).

Need to find a way to stop wasting resources on repaints if nobody's watching.

GCal set schedule not updating app

Problem: Host machine restart broke schedule update in app. Restart was for a problem with another project (not dz related).

Git branch version:
`$ git branch -v

Steps taken to resolve:

  • Renew {HOME}/.dz/Calendar/StoredCredential in case it had expired (have to run "$./dz-runner | grep https" to get url, local port forward to headless machine the port specified in the authentication URL, paste url in local browser and sign in. SortedCredential was verified as updated) => no success
  • Renew app-specific password in dz3 conf file in the http-connector section => no success
  • restart dz service => no success
  • restart machine => no success

The error (occurs every minute in logs) is:

16:01:10,052 ERROR Scheduler pool-13-thread-1 [run] Unexpected exception
java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
at net.sf.dz3.scheduler.gcal.StatusParser.parse(StatusParser.java:77)
at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.parseEvent(GCalScheduleUpdater.java:322)
at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.updateEvent(GCalScheduleUpdater.java:290)
at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.parse(GCalScheduleUpdater.java:261)
at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.parseEvents(GCalScheduleUpdater.java:243)
at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.updateCalendar(GCalScheduleUpdater.java:181)
at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.update(GCalScheduleUpdater.java:126)
at net.sf.dz3.scheduler.Scheduler.update(Scheduler.java:265)
at net.sf.dz3.scheduler.Scheduler.run(Scheduler.java:229)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

Once setpoint is changed, the zone never returns to schedule

How to reproduce:

  • In cooling mode with active scheduler, move the setpoint away from the schedule defined one
  • Expected behavior: zone setpoint returns to schedule when next period starts
  • Actual behavior: once changed, setpoint stays as if the zone is put on hold

Make sure only averaged values participate in autoscaling

Fast changing temperature sources (example: CPU sensor) will produce values that will not be renderable given the current spacing algorithm (which is, average values per pixel of width, display the pixel). However, they are used to calculate autoscale limits.

Need to change autoscaling algorithm to only take averaged values into account.

Possible future extension: display the averaged value, and min/max range per pixel (similar to a candlestick chart or Bollinger bands).

File based usage counter blows up if the persistent storage doesn't exist

Workaround: touch ${persistent-storage-file}

Trace:

java.io.FileNotFoundException: ${persistent-storage-file-removed-for-privacy} (No such file or directory)
        at java.io.FileOutputStream.open(Native Method)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:212)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:99)
        at java.io.FileWriter.<init>(FileWriter.java:63)
        at net.sf.dz3.util.counter.FileUsageCounter.save(FileUsageCounter.java:158)

Remove deprecated settings from Gradle build files

Current Gradle build issues this warning:

Deprecated Gradle features were used in this build, making it incompatible with Gradle 5.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/4.9/userguide/command_line_interface.html#sec:command_line_warnings

Make Swing UI react to mouse gestures

Currently, Swing UI only reacts to keyboard input (arrows to change zones/setpoint, C/F to switch between Celsius and Fahrenheit, O to switch a zone on/off, H to change hold status and V to change voting status.

Need to implement mouse input to make Swing console behave the same way Android UI does.

EmptyStackException on Google calendar updates

Symptoms: EmptyStackException trace below in the log.
Cause: Google Calendar bug or feature that makes recurring events stop after 2 years.
Fix: manually clone recurring events so they cover the correct time span.

java.util.EmptyStackException
        at java.util.Stack.peek(Stack.java:102)
        at java.util.Stack.pop(Stack.java:84)
        at net.sf.dz3.scheduler.PeriodMatcher.match(PeriodMatcher.java:57)
        at net.sf.dz3.scheduler.gcal.GCalScheduleUpdaterTest.testEvents(GCalScheduleUpdaterTest.java:172)
        at net.sf.dz3.scheduler.gcal.GCalScheduleUpdaterTest.testDST(GCalScheduleUpdaterTest.java:104)

Prolific PL2303 USB-Serial Controller doesn't work on some Pi/Raspbian combinations

Symptoms: after connecting the PL2303 adapter to a USB port, or booting with it already plugged in, /dev/ttyUSB0 doesn't appear.

Known to work on:

  • Raspberry Pi 2 Model B running Raspbian Wheezy
  • Raspberry Pi 2 Model B running Raspbian Jessie
  • Raspberry Pi 3 Model B running Raspbian Jessie
  • Raspberry Pi 3 Model B running Raspbian Stretch

Known NOT to work on:

  • Raspberry Pi 2 Model B running Raspbian Stretch

It is not known at this time whether missing /dev/ttyUSB0 is specific to Prolific USB-Serial Controller, or any USB-Serial Controller. However, as it was noted in Supported Hardware, using FTDI based USB-Serial Controller is preferable, and using Prolific controllers is discouraged.

This issue will stay open to attract attention.

Power brownout/blackout on XBee relay board may cause catastrophic runaway loop

What steps will reproduce the problem?

  1. Start the system normally with XBee relay board controlling a HVAC device, in non-default mode (the mode relay must be energized)
  2. Cycle power on XBee relay board
  3. Cause the HVAC device to turn on

What is the expected output?

HVAC turns on heating when heating is required, and cooling when cooling required

What do you see instead?

HVAC device starts in the wrong mode (heating instead of cooling or the other way around).

This will cause a runaway loop with potentially catastrophic consequences when a HVAC device is unattended. Workaround: have the XBee relay board on UPS. More permanent solution is coming.

Appointments that traverse midnight in google calendar break

Appointments traversing midnight on Google calendar. Stop working at midnight

Steps to reproduce problem:

  1. Make heating appointment that traverses midnight, eg from 10pm on the
    20th of June until 7am on the 21st of June

Expected out come: dz maintains setpoint for the duration of appointment for
the specified zone

Actual outcome: appointment terminated at or near midnight

Current work-around: make 2 appointments; one from 10pm until 11:59pm on the
20th and one from 00:01am until 7am on the 21st of June

DamperMultiplexer#park() expected and actual behavior differ

ParkingAssistant#execute() seems to report a generic park position that was supplied for DamperMultiplexer itself, however, it also seems to park each nested damper where individual damper configuration prescribes.

Need to correct the logic and logging, and provide a test suite to confirm correct operation.

Change path to commons-codec in classpath

HI Vadim, I can't create a pull request as not authorised to push to repo, so can you please change this line in dz3-shell/classpath:
${LIBDIR}/commons-codec-1.2.jar:\

to:
${LIBDIR}/commons-codec-1.3.jar:\

Cheers!

Marcus

Optimize setpoint rendering

#33 draws the setpoint in a wasteful and redundant way, involves storing redundant setpoint values all over the time span of the chart and iterating through all of them repeatedly. Need to eliminate storing redundant values, and related calculations.

"proto3" .proto files fail to compile on Raspbian Wheezy and Jessie

Root cause: protoc (part of protobuf-compiler package) version is too old (2.4.1-3 on Wheezy, 2.6.1-1 on Jessie). protobuf starting from version 3.0 is required to support proto3 syntax.

This will not be fixed unless there's significant demand. proto3 offers about 40% wire size improvement over proto2 and puts unnecessary load on the server.

Fix: upgrade to Raspbian Stretch.

Zone schedule is not set until the sensor is detected after startup

  • Expected result: the schedule is set on the zone
  • Actual result: the schedule is not set and an exception trace is repeatedly logged until the sensor appears.

Exception trace:

14:27:28,443 ERROR Scheduler pool-20-thread-1 [run execute] Dining Room: failed to set schedule, will retry on next run
java.lang.NullPointerException
        at net.sf.dz3.controller.pid.AbstractPidController.compute(AbstractPidController.java:236)
        at net.sf.dz3.controller.AbstractProcessController.wrapCompute(AbstractProcessController.java:163)
        at net.sf.dz3.controller.AbstractProcessController.setSetpoint(AbstractProcessController.java:73)
        at net.sf.dz3.device.model.impl.ThermostatModel.setSetpoint(ThermostatModel.java:360)
        at net.sf.dz3.device.model.impl.ThermostatModel.set(ThermostatModel.java:513)
        at net.sf.dz3.scheduler.Scheduler.execute(Scheduler.java:353)
        at net.sf.dz3.scheduler.Scheduler.execute(Scheduler.java:315)
        at net.sf.dz3.scheduler.Scheduler.run(Scheduler.java:230)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:744)

Replace XML master configuration with something more compact

Currently used XML configuration originated in year 2000 when XML was all the rage (and actually a novelty). It is now hopelessly obsolete.

Need to find a way to simplify it.

Candidates:

  • JSON - simpler to implement, but still cryptic
  • YAML - more difficult, but most end user friendly if done right

Change setpoint's role in autoscaling

Currently, the chart is autoscaled both on temperature and setpoint values. This may cause the chart to flatten out and become less informative if it is deeply in "happy" zone (example: "cool the server room to 30°C" in the winter when the temperature may drop to below 20°C) - but temperature variations are still important.

One possible option: if the setpoint is beyond the chart into the "happy" zone, then autoscale on values only, and display the arrow pointing into setpoint direction.

Need to gracefully back off from over-quota server

Currently, v2.HttpConnector doesn't recognize the "503 Over Quota" server response and keeps pounding the server with requests (which, depending on server policy and/or implementation, may incur charges or degrade performance). Need to recognize this situation and gracefully back off until the situation is remedied. Reference: Addressing Cascading Failures.

Sample log (against commit d50049f47720f89168b30f764439688f21fe1401):

00:12:17,228 ERROR HttpConnector$ZoneSnapshotExchanger pool-22-thread-1 [execute exchange] HTTP rc=503, text follows:
00:12:17,233 ERROR HttpConnector$ZoneSnapshotExchanger pool-22-thread-1 [execute exchange] 
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>503 Over Quota</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<table border=0 cellpadding=2 cellspacing=0 width=100%>
<tr><td bgcolor=#3366cc><font face=arial,sans-serif color=#ffffff><b>Error</b></td></tr>
<tr><td>&nbsp;</td></tr></table>
<blockquote>
<H1>Over Quota</H1>
This application is temporarily over its serving quota.  Please try again later.

<p>
</blockquote>
<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=#3366cc><img alt="" width=1 height=4></td></tr></table>
</body></html>

00:12:17,236 ERROR HttpConnector$ZoneSnapshotExchanger pool-22-thread-1 [execute exchange] Buffer exchange failed
java.io.IOException: Request failed with HTTP code 503
        at net.sf.dz3.view.http.v2.HttpConnector$ZoneSnapshotExchanger.exchange(HttpConnector.java:199)
        at net.sf.dz3.view.http.common.BufferedExchanger.execute(BufferedExchanger.java:79)
        at net.sf.jukebox.service.ActiveService$ExecWrapper.call(ActiveService.java:94)
        at net.sf.jukebox.service.PassiveService.wrap(PassiveService.java:746)
        at net.sf.jukebox.service.ActiveService$ActiveWrapper.run(ActiveService.java:160)
        at java.lang.Thread.run(Thread.java:744)

RXTX not playing nicely with symlinked USB-1Wire adaptors

Problem: Can't connect DZ3 to the symlinked address assigned in udev rule

Issue causing problem: I have 2 usb devices that must have a consistent port for process to sniff data coming from/going to port

udev rule works great for assigning port:

ls -l /dev | grep DZ3
gives:
lrwxrwxrwx 1 root root 7 Mar 5 19:37 DZ3 -> ttyUSB1

conf file snip:

<bean id="device_factory" class="net.sf.dz3.device.sensor.impl.onewire.OwapiDeviceFactory" init-method="start">
                <constructor-arg index="0" value="/dev/DZ3"/>
                <constructor-arg index="1" value="regular"/>
    </bean>

Error message:

19:41:18,281 ERROR OwapiDeviceFactory pool-3-thread-1 [] Uncaught exception: 
java.lang.IllegalArgumentException: Port '/dev/DZ3' unavailable, valid values: [/dev/ttyUSB1, /dev/ttyUSB2]

Is this an upstream problem with rxtx stuff or similar?

I will just poll port in meantime and change config to suit so not a critical issue

marcus

Zone temperature chart needs to include setpoint

Currently, the chart reflects only temperature, signal, and HVAC on/off state, but not the setpoint. Cases of "thermostat wars" were observed when users were setting the temperature too high or too low within seconds from each other, not knowing that the other person has just adjusted the setpoint and thinking that setpoint needs to be adjusted further.

Having setpoint history information on the chart will eliminate this problem.

java.lang.UnsatisfiedLinkError: no rxtxSerial in java.library.path thrown while loading gnu.io.RXTXCommDriver

Symptoms: log messages and exception trace below. The message above will not get in any logs and will only be displayed on the console due to the way RxTx works. Watch the startup log of dz-runner carefully to catch it, or use tee(1).

Fix: add the following option to java binary invocation in dz-runner:

-Djava.library.path="/usr/lib/jni"

It is possible that the path will be different, find the actual location by executing this command:

locate rxtxSerial

Error message to watch for in the logs:

    02:45:21,466 WARN OneWireAccessProvider pool-3-thread-1 [startup getPortsAvailable] Could not load serial comm API for pure-Java DS9097U adapter.
    02:45:21,467 WARN OneWireAccessProvider pool-3-thread-1 [startup getPortsAvailable] This message can be safely ignored if you are using TMEX Drivers or
    02:45:21,468 WARN OneWireAccessProvider pool-3-thread-1 [startup getPortsAvailable] the NetAdapter to connect to the 1-Wire Network.
    02:45:21,469 ERROR OneWireAccessProvider pool-3-thread-1 [startup getPortsAvailable] Standard drivers for 1-Wire are not found.
    02:45:21,470 ERROR OneWireAccessProvider pool-3-thread-1 [startup getPortsAvailable] Please download the latest drivers from http://www.ibutton.com 
    02:45:21,471 ERROR OneWireAccessProvider pool-3-thread-1 [startup getPortsAvailable] Or install RXTX Serial Communications API from http://www.rxtx.org 
    02:45:21,503 ERROR OwapiDeviceFactory pool-3-thread-1 [] Uncaught exception: 
    java.lang.IllegalArgumentException: Port '/dev/ttyUSB0' unavailable, valid values: []
    Things to check:
        http://stackoverflow.com/questions/9628988/ubuntu-rxtx-does-not-recognize-usb-serial-device yet?
            at net.sf.dz3.device.sensor.impl.onewire.OwapiDeviceFactory.startup(OwapiDeviceFactory.java:209)
            at net.sf.jukebox.service.PassiveService$StartupWrapper.call(PassiveService.java:477)
            at net.sf.jukebox.service.PassiveService.wrap(PassiveService.java:746)
            at net.sf.jukebox.service.ActiveService$ActiveWrapper.run(ActiveService.java:149)
            at java.lang.Thread.run(Thread.java:745)

Allow SwitchDamper to invert the underlying switch state

Currently, SwitchDamper only supports straight configuration:

  • 1.0 damper position means true switch state
  • 0.0 damper position means false switch state

Need to support configurations where switch state is inverted:

  • 1.0 damper position means false switch state
  • 0.0 damper position means true switch state

Google Calendar Updater is broken on Raspbian Stretch

Invocation results in the following exception thrown:

    22:00:09,715 ERROR Scheduler pool-5-thread-1 [run] Unexpected exception
    java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
            at com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver.getRedirectUri(LocalServerReceiver.java:98)
            at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.authorize(AuthorizationCodeInstalledApp.java:76)
            at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.authorize(GCalScheduleUpdater.java:447)
            at net.sf.dz3.scheduler.gcal.GCalScheduleUpdater.update(GCalScheduleUpdater.java:92)
            at net.sf.dz3.scheduler.Scheduler.update(Scheduler.java:265)
            at net.sf.dz3.scheduler.Scheduler.run(Scheduler.java:229)
            at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
            at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
            at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
            at java.lang.Thread.run(Thread.java:748)
    Caused by: java.lang.ClassNotFoundException: javax.servlet.http.HttpServletRequest
            at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
            at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
            ... 13 more

Possible slow memory leak related to TintedValue

TintedValue object count grows with time. Suspect: LinkedHashMap.keySet().iterator().remove() in data sets.

Workaround: none needed, the leak is slow enough not to have any effect for months.

Fix the setpoint rendering when the zone is off

Currently, the setpoint for a disabled zone is still rendered on the chart (and participates in autoscaling). Need to take it out of consideration for the time period when the zone is off.

Schedule is one hour off when on DST

(Clone of https://code.google.com/p/diy-zoning/issues/detail?id=10)

What steps will reproduce the problem?

  1. Set up google schedule

What is the expected output? What do you see instead?
Expected output is schedules following time :-)
Actual output - after time changed to daylight saving time dz moved all events one hour ahead.

What version of the product are you using? On what operating system?
Ubuntu 10.4, 3.6.4 SNAPSHOT

Please provide any additional information below.
I would say that it's double conversion. If I have calendar scheduled to be from xx to 8pm CST (GMT-6) and right now I have 7pm CDT (GMT-5) that means that it's 6pm CST (GMT-6) right? And yet DZ acted like it was already 8pm. If DZ stayed in central time it should do things 1h too late not too soon.

So to me it looks like google is making magic conversion returning CDT times (already moved ahead) but marked as CST and then my java (or dz) converts them again from supposedly CST to CDT, moving them ahead one more time.

GCalScheduleUpdaterTest#testDST() fails

As of commit e65981619065fbf82378be61e629ab403401be1a, GCalScheduleUpdaterTest#testDST() fails with the following message:

22:40:33,164 ERROR GCalScheduleUpdaterTest main [testDST] Oops
 org.junit.ComparisonFailure: Wrong period matched expected:<1[8 - 19]> but was:<1[7 - 18 phx]>
	at org.junit.Assert.assertEquals(Assert.java:115) ~[junit-4.12.jar:4.12]
	at net.sf.dz3.scheduler.gcal.GCalScheduleUpdaterTest.testEvents(GCalScheduleUpdaterTest.java:184) ~[test-classes/:?]
	at net.sf.dz3.scheduler.gcal.GCalScheduleUpdaterTest.testDST(GCalScheduleUpdaterTest.java:112) [test-classes/:?]

Swing Console repainted twice on update

One signal update call causes two repaints. There's a chance that when this was originally implemented this was not the case, but throughout the years Swing behavior changed and now the console is doing twice as much work as it needs to.

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.