diff --git a/app/modbus-data-viewer/.gitignore b/app/modbus-data-viewer/.gitignore
new file mode 100644
index 0000000..9aca816
--- /dev/null
+++ b/app/modbus-data-viewer/.gitignore
@@ -0,0 +1,4 @@
+bin/
+pkg/
+src/github.com/
+release/
diff --git a/app/modbus-data-viewer/build.sh b/app/modbus-data-viewer/build.sh
new file mode 100755
index 0000000..bb730ca
--- /dev/null
+++ b/app/modbus-data-viewer/build.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+GOPATH=$PWD go get -v service-web
+GOPATH=$PWD GOARCH=arm GOOS=linux go install service-web
diff --git a/app/modbus-data-viewer/release.sh b/app/modbus-data-viewer/release.sh
new file mode 100755
index 0000000..4b430dd
--- /dev/null
+++ b/app/modbus-data-viewer/release.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+./build.sh
+
+if [ ! -d release ]; then
+  mkdir release
+else
+  rm -rf release/*
+fi
+
+cp bin/linux_arm/service-web release/service-web
+cp -rf src/service-web/templates release/
diff --git a/app/modbus-data-viewer/src/service-web/main.go b/app/modbus-data-viewer/src/service-web/main.go
new file mode 100644
index 0000000..6e27124
--- /dev/null
+++ b/app/modbus-data-viewer/src/service-web/main.go
@@ -0,0 +1,104 @@
+package main
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+	"html/template"
+	"log"
+	"net"
+	"sync"
+
+	"github.com/codegangsta/martini"
+	"github.com/codegangsta/martini-contrib/render"
+)
+
+type Header int32
+type Packet [50]uint16
+
+var mutex sync.Mutex
+var templateMap = make(map[string]interface{})
+var controlTable, stateTable string
+
+func main() {
+	go ListenUDP()
+
+	m := martini.Classic()
+
+	m.Use(render.Renderer())
+
+	m.Get("/", func(r render.Render) {
+		mutex.Lock()
+		defer mutex.Unlock()
+
+		r.HTML(200, "main", templateMap)
+	})
+
+	m.Run()
+}
+
+func ListenUDP() {
+	addr, err := net.ResolveUDPAddr("udp", ":40001")
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	conn, err := net.ListenUDP("udp", addr)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer conn.Close()
+
+	for {
+		b := make([]byte, 1024)
+		_, _, err := conn.ReadFromUDP(b)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		buf := bytes.NewReader(b)
+
+		var header Header
+		err = binary.Read(buf, binary.LittleEndian, &header)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		var packet Packet
+		err = binary.Read(buf, binary.LittleEndian, &packet)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		switch header {
+		case 0:
+			mapControl(packet)
+		case 1:
+			mapState(packet)
+		}
+	}
+}
+
+func mapControl(packet Packet) {
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	controlTable = ""
+	for i, v := range packet {
+		controlTable += fmt.Sprintf("<tr><td>%v</td><td>0x%04X</td><td>0x%04X</td><td>%d</td></tr>\n", 30001+i, i, v, v)
+	}
+
+	templateMap["Table_Control"] = template.HTML(controlTable)
+}
+
+func mapState(packet Packet) {
+	mutex.Lock()
+	defer mutex.Unlock()
+
+	stateTable = ""
+	for i, v := range packet {
+		stateTable += fmt.Sprintf("<tr><td>%v</td><td>0x%04X</td><td>0x%04X</td><td>%d</td></tr>\n", 40001+i, i, v, v)
+	}
+
+	templateMap["Table_State"] = template.HTML(stateTable)
+}
diff --git a/app/modbus-data-viewer/src/service-web/templates/main.tmpl b/app/modbus-data-viewer/src/service-web/templates/main.tmpl
new file mode 100644
index 0000000..6fafd4f
--- /dev/null
+++ b/app/modbus-data-viewer/src/service-web/templates/main.tmpl
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <style>
+th, td { padding: 0.5em }
+table.data
+{
+    display: inline-block;
+    text-align: right;
+    font-family: monospace;
+    font-size: 1.2em;
+    border: 1px solid black;
+}
+    </style>
+  </head>
+  <body>
+    <table class="data">
+      <tr>
+        <th>Address</th>
+        <th>Address</th>
+        <th>Value</th>
+        <th>Value</th>
+      </tr>
+      <tr>
+        <th>(Dec)</th>
+        <th>(Hex)</th>
+        <th>(Hex)</th>
+        <th>(Dec)</th>
+      </tr>
+{{.Table_Control}}
+    </table>
+    <table class="data">
+      <tr>
+        <th>Address</th>
+        <th>Address</th>
+        <th>Value</th>
+        <th>Value</th>
+      </tr>
+      <tr>
+        <th>(Dec)</th>
+        <th>(Hex)</th>
+        <th>(Hex)</th>
+        <th>(Dec)</th>
+      </tr>
+{{.Table_State}}
+    </table>
+  </body>
+</html>