diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1fdc3ded417d6941e7592b867d635fa9ff813ed7..40f247c46b3c7e9bc20a1d7379c46e2a70fd0fea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,8 +1,7 @@
 cmake_minimum_required(VERSION 3.6)
 
 project(SmartGridModell)
-set(CMAKE_CXX_STANDARD 11)
-add_compile_options(-Wall -Wextra -pedantic)
+set(CMAKE_CXX_STANDARD 17)
 
 # Add spdlog for nice and easy logging
 add_subdirectory(libs/spdlog)
@@ -30,6 +29,27 @@ add_executable(smart_grid.exe
     src/i2c/Node.cpp
     src/com/Socket.cpp
     src/com/Protocol.cpp
+    src/ModelState.cpp
 )
 
 target_link_libraries(smart_grid.exe spdlog)
+target_compile_options(smart_grid.exe PRIVATE -Wall -Wextra -pedantic)
+
+
+# Add OPC UA
+# macro(SET_OPTION option value)
+#   set(${option} ${value} CACHE "" INTERNAL FORCE)
+# endmacro()
+option(BUILD_CLIENT "Build Client" OFF)
+option(BUILD_SERVER "Build Server" ON)
+
+option(SSL_SUPPORT_MBEDTLS "Support rsa-oaep password encryption using mbedtls library " OFF)
+
+option(BUILD_PYTHON "Build Python bindings" OFF)
+option(BUILD_TESTING "Build and run tests" OFF)
+option(BUILD_SHARED_LIBS "Build shared libraries." ON)
+add_subdirectory(libs/freeopcua)
+
+add_executable(opc_server.exe src/opc_server.cpp)
+target_include_directories(opc_server.exe PUBLIC libs/freeopcua/include)
+target_link_libraries(opc_server.exe opcuacore opcuaserver)
\ No newline at end of file
diff --git a/src/ModelState.cpp b/src/ModelState.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..22c19b01ed4c7ea164a10470b2fa093298dc11bc
--- /dev/null
+++ b/src/ModelState.cpp
@@ -0,0 +1,117 @@
+/// @file   ModelState.cpp
+///
+
+#include "ModelState.hpp"
+
+
+ModelState::ModelState(SmartGridModell &modell)
+    : m_modell(modell)
+{
+    std::srand(std::time(nullptr));
+}
+
+void ModelState::update_wind()
+{
+    double wind_by_sun = m_sun * 7.0 / 100.0; // wind by sun should by 5 max.
+    auto random_wind = ((std::rand() * 1.0) / RAND_MAX) * 5.0;
+    m_wind = power_wind[static_cast<int>(wind_by_sun + random_wind)];
+}
+
+
+void ModelState::update_modell()
+{
+    auto sun = m_sun * 2.5;
+    auto wind = m_wind / 8.3;
+    auto renewable = (sun + wind) / 2;
+    m_modell.set_solar_plant(sun);
+    m_modell.update_windmill_speed(wind);
+    m_modell.set_windmill_net(wind);
+    m_modell.set_renewable_net(renewable);
+    if (m_production.conventional > 0)
+    {
+        m_modell.set_power_plant(200);
+        m_modell.set_village_color(200, renewable);
+    }
+    else
+    {
+        m_modell.set_power_plant(0);
+        m_modell.set_village_color(0, renewable);
+    }
+}
+
+
+void ModelState::update_power_production()
+{
+     m_production.renewable.solar = m_sun * solar_size;
+    m_production.renewable.wind = m_wind * windpark_size;
+    if (m_usage.sum() > m_production.clean())
+    {
+        m_excess_power = 0.0;
+        m_production.conventional = m_usage.sum() - m_production.clean();
+    }
+    else
+    {
+        m_excess_power = m_production.clean() - m_usage.sum();
+        m_production.conventional = 0;
+    }
+}
+
+
+double ModelState::excess_power()
+{
+    auto sum_prod = m_production.conventional + m_production.renewable.solar + m_production.renewable.wind;
+    auto sum_used = m_usage.industry + m_usage.village;
+    return sum_prod - sum_used;
+}
+
+
+void ModelState::update_power_consumption()
+{
+    m_usage.village = village_consumption_at[m_time] * village_size;
+    if (m_producing == true)
+    {
+        m_usage.industry = MaxPower::industry;
+    }
+    else
+    {
+        m_usage.industry = 0.0;
+    }
+}
+
+void ModelState::update_time()
+{
+    if (m_time < 23)
+    {
+        ++m_time;
+    }
+    else
+    {
+        m_time = 0;
+    }
+}
+
+void ModelState::update_sun()
+{
+    m_sun = sunnshine_percentage[m_time];
+}
+
+
+void ModelState::print_states()
+{
+    spdlog::debug("Time         <{}> Sun     <{}> Wind<{}>", m_time, m_sun, m_wind);
+    spdlog::debug("Power Conv   <{}> Solar   <{}> Wind<{}>", m_production.conventional, m_production.renewable.solar, m_production.renewable.wind);
+    spdlog::debug("Usage Village<{}> Industry<{}>", m_usage.village, m_usage.industry);
+    spdlog::debug("excess_power<{}>", excess_power());
+}
+
+
+void ModelState::next_hour()
+{
+    update_time();
+    update_sun();
+    update_wind();
+    update_power_consumption();
+    update_power_production();
+    update_modell();
+    print_states();
+}
\ No newline at end of file
diff --git a/src/ModelState.hpp b/src/ModelState.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..86c90127d986126416f284fb9fb38049a091aa24
--- /dev/null
+++ b/src/ModelState.hpp
@@ -0,0 +1,89 @@
+/// @file   ModelState.hpp
+///
+
+#ifndef MODEL_STATE_HPP
+#define MODEL_STATE_HPP
+
+#include <cstdlib>
+#include <ctime>
+
+#include "spdlog/spdlog.h"
+#include "SmartGridModell.hpp"
+
+struct MaxPower
+{
+    static constexpr double village = 600;
+    static constexpr double industry = 200;
+    static constexpr double wind = 250;
+    static constexpr double solar = 110;
+};
+
+constexpr double village_consumption_at[]{
+    98, 95, 93, 94, 95, 101, 115,
+    127, 132, 134, 136, 139, 138,
+    136, 134, 132, 130, 132, 132,
+    131, 125, 119, 114, 105, 98};
+
+constexpr double sunnshine_percentage[]{
+    0, 0, 0, 0, 0, 0, 3,
+    12, 30, 52, 73, 88, 97,
+    100, 98, 91, 81, 66, 46,
+    25, 10, 2, 0, 0, 0};
+
+constexpr double power_wind[]{
+    0, 3, 25, 82, 174,
+    321, 532, 815, 1180,
+    1612, 1890, 2000, 2100};
+
+struct CleanPower
+{
+    double solar = 0.0;
+    double wind = 0.0;
+};
+
+struct PowerProduction
+{
+    double conventional;
+    CleanPower renewable;
+    double clean() { return renewable.solar + renewable.wind; }
+    double sum() { return conventional + clean(); }
+};
+
+struct PowerUsage
+{
+    double village = 0.0;
+    double industry = 0.0;
+    double sum() { return village + industry; }
+};
+
+class ModelState
+{
+public:
+    ModelState(SmartGridModell &modell);
+    void next_hour();
+    double excess_power();
+
+private:
+    void update_time();
+    void update_sun();
+    void update_wind();
+    void update_power_consumption();
+    void update_power_production();
+    void update_modell();
+    void print_states();
+
+    static constexpr double solar_size{10};
+    static constexpr double windpark_size{1.0};
+    static constexpr double village_size{10};
+
+    int m_time{0};
+    double m_sun{0};
+    double m_wind{0};
+    double m_excess_power{0.0};
+    PowerProduction m_production;
+    PowerUsage m_usage;
+    bool m_producing{false};
+    SmartGridModell &m_modell;
+};
+
+#endif
\ No newline at end of file
diff --git a/src/SmartGridModell.cpp b/src/SmartGridModell.cpp
index c8ca1a71505b66fe59eef1bd353d81c3a1cf1a46..c51bbef76854351c6f8e6f218dfc110e3055d0d6 100644
--- a/src/SmartGridModell.cpp
+++ b/src/SmartGridModell.cpp
@@ -12,6 +12,11 @@ SmartGridModell::SmartGridModell(i2c::Node& node, DefaultState initial_state)
     put_modell_into_state(initial_state);
 }
 
+SmartGridModell::~SmartGridModell()
+{
+    put_modell_into_state(DefaultState::Off);
+}
+
 
 void SmartGridModell::put_modell_into_state(DefaultState state)
 {
diff --git a/src/SmartGridModell.hpp b/src/SmartGridModell.hpp
index cee45b00e1ca820950fe0bb663d3948a0c1a8ead..de4f792812aa961f141285d857f90f2bc1ba0587 100644
--- a/src/SmartGridModell.hpp
+++ b/src/SmartGridModell.hpp
@@ -58,6 +58,9 @@ public:
     ///
     SmartGridModell(i2c::Node& node, DefaultState initial_state = DefaultState::Off);
 
+    ~SmartGridModell();
+
+
     /// @brief Put the to one of the predefined states.
     /// 
     /// @param state Default state to which the modell will be changed.
diff --git a/src/i2c/Node.cpp b/src/i2c/Node.cpp
index b354266ad251d85660e722d4e4389160ad92f8fe..3ee42ead9463192a95deedfb8d0376213771fc57 100644
--- a/src/i2c/Node.cpp
+++ b/src/i2c/Node.cpp
@@ -9,11 +9,9 @@
 
 using namespace i2c;
 
-Node::Node(uint8_t node_address) 
-    : m_address{node_address}
-    , m_device{-1}
+Node::Node(uint8_t node_address)
+    : m_address{node_address}, m_device{-1}
 {
-
 }
 
 Node::~Node()
@@ -21,7 +19,7 @@ Node::~Node()
     close(m_device);
 }
 
-bool Node::open_device(const char* i2c_device_name)
+bool Node::open_device(const char *i2c_device_name)
 {
     auto fd = open(i2c_device_name, O_RDWR);
     if (fd < 0)
@@ -39,9 +37,7 @@ bool Node::open_device(const char* i2c_device_name)
     return true;
 }
 
-
-
-bool Node::send(uint8_t* data, ssize_t size)
+bool Node::send(uint8_t *data, ssize_t size)
 {
     ssize_t bytes_written = write(m_device, data, size);
     if (bytes_written != size)
@@ -54,7 +50,7 @@ bool Node::send(uint8_t* data, ssize_t size)
 
 bool Node::send(std::vector<uint8_t> &data)
 {
-    return send(data.data(), data.size());  
+    return send(data.data(), data.size());
 }
 
 bool Node::send(std::array<uint8_t, 2> &data)
@@ -64,15 +60,14 @@ bool Node::send(std::array<uint8_t, 2> &data)
 
 bool Node::send(uint8_t reg, uint8_t val)
 {
-    uint8_t data[2] {reg, val};
+    uint8_t data[2]{reg, val};
     return send(data, 2);
 }
 
-
 constexpr uint8_t i2c_smbus_max_block_size = 32;
 struct i2c_data
 {
-    uint8_t block [i2c_smbus_max_block_size + 2];
+    uint8_t block[i2c_smbus_max_block_size + 2];
 };
 
 struct i2c_ioctl_data
@@ -80,7 +75,7 @@ struct i2c_ioctl_data
     char read_write;
     uint8_t command;
     int size;
-    i2c_data* data;
+    i2c_data *data;
 };
 
 int Node::read16(uint8_t reg_addr)
@@ -100,7 +95,7 @@ int Node::read16(uint8_t reg_addr)
     }
     else
     {
-        int answer {0};
+        int answer{0};
         answer |= static_cast<int>(data.block[0] << 8); // MSB
         answer |= static_cast<int>(data.block[1] << 0); // LSB
         spdlog::debug("Received data: {} {} converted to {}.", data.block[0], data.block[1], answer);
diff --git a/src/opc_server.cpp b/src/opc_server.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cb33b8e89e8e5ad2fe93a734e1eb64c9a55e27f7
--- /dev/null
+++ b/src/opc_server.cpp
@@ -0,0 +1,49 @@
+/// @file opc_server.cpp
+///
+
+#include <opc/ua/node.h>
+#include <opc/ua/server/server.h>
+
+using namespace OpcUa;
+
+
+
+std::vector<OpcUa::Variant> my_method(NodeId context, std::vector<OpcUa::Variant> arguments)
+{
+    std::cout << "Method triggered" << std::endl;
+    
+    std::vector<OpcUa::Variant> result;
+    result.push_back(Variant(static_cast<uint8_t>(0)));
+    return result;
+}
+
+void add_nodes_to(uint32_t idx, Node &objects)
+{
+    Node smart_grid = objects.AddFolder(idx, "smart_grid");
+    Node renewable = smart_grid.AddVariable(idx, "renewable_power", Variant(42.0));
+    Node prop = smart_grid.AddProperty(idx, "a_property_thin", Variant("something"));
+    Node method = smart_grid.AddMethod(idx, "trigger_method_x", my_method);
+}
+
+
+int main(int argc, char **argv)
+{
+    auto logger = spdlog::stderr_color_mt("server");
+    OpcUa::UaServer server(logger);
+
+    server.SetEndpoint("opc.tcp://localhost:4840/opcua/smartgridserver");
+    server.SetServerURI("Smart Grid OPC UA Server");
+    server.Start();
+
+    auto idx = server.RegisterNamespace("smart-grid");
+    Node objects = server.GetObjectsNode();
+
+    add_nodes_to(idx, objects);
+
+    while (true)
+    {
+        std::this_thread::sleep_for(std::chrono::seconds(1));
+    }
+
+    return 0;
+}
\ No newline at end of file