diff --git a/config/config.js b/config/config.js new file mode 100644 index 0000000000000000000000000000000000000000..7a6ca8d8f0bcefe562c1c9900bcb4af0219db127 --- /dev/null +++ b/config/config.js @@ -0,0 +1,26 @@ +module.exports = { + development: { + passport: { + strategy: 'saml', + saml: { + path: process.env.SAML_PATH || '/saml/SSO', + entryPoint: process.env.SAML_ENTRY_POINT || 'https://m4lab.hft-stuttgart.de/idp/saml2/idp/SSOService.php', + issuer: 'sp-account.m4lab.hft-stuttgart.de', //local metadata + logoutUrl: 'https://m4lab.hft-stuttgart.de/idp/saml2/idp/SingleLogoutService.php' + } + } + }, + test: { + passport: { + strategy: 'saml', + saml: { + path: process.env.SAML_PATH || '/saml/SSO', + entryPoint: process.env.SAML_ENTRY_POINT || 'https://m4lab.hft-stuttgart.de/idp/saml2/idp/SSOService.php', + issuer: 'sp-account-testing.m4lab.hft-stuttgart.de', //testing metadata + //issuer: 'sp-account-prod.m4lab.hft-stuttgart.de', //production metadata + logoutUrl: 'https://m4lab.hft-stuttgart.de/idp/saml2/idp/SingleLogoutService.php' + } + } + } + }; + \ No newline at end of file diff --git a/config/routes.js b/config/routes.js new file mode 100644 index 0000000000000000000000000000000000000000..5b8be77e762ffc89cd9192a653040303bb0e7c47 --- /dev/null +++ b/config/routes.js @@ -0,0 +1,103 @@ +const fs = require('fs'); +const SamlStrategy = require('passport-saml').Strategy; + +module.exports = function (app, config, passport) { + + // =========== PASSPORT ======= + passport.serializeUser(function (user, done) { + done(null, user); + }); + + passport.deserializeUser(function (user, done) { + done(null, user); + }); + + var samlStrategy = new SamlStrategy({ + // URL that goes from the Identity Provider -> Service Provider + callbackUrl: config.passport.saml.path, + // Base address to call logout requests + logoutUrl: config.passport.saml.logoutUrl, + + entryPoint: config.passport.saml.entryPoint, + issuer: config.passport.saml.issuer, + identifierFormat: null, + + // Service Provider private key + decryptionPvk: fs.readFileSync(__dirname + '/cert/key.pem', 'utf8'), + + // Service Provider Certificate + privateCert: fs.readFileSync(__dirname + '/cert/key.pem', 'utf8'), + //privateCert: fs.readFileSync(__dirname + '/cert/cert.pem', 'utf8'), + + // Identity Provider's public key + cert: fs.readFileSync(__dirname + '/cert/cert_idp.pem', 'utf8'), + + validateInResponseTo: false, + disableRequestedAuthnContext: true + }, + function (profile, done) { + return done(null, + { + id: profile.nameID, + idFormat: profile.nameIDFormat, + email: profile.email, + firstName: profile.givenName, + lastName: profile.sn + }); + }); + + passport.use(samlStrategy); + // ============================ + + app.get('/login', + passport.authenticate(config.passport.strategy, + { + successRedirect: '/', + failureRedirect: '/login' + }) + ); + + app.post(config.passport.saml.path, + passport.authenticate(config.passport.strategy, + { + failureRedirect: '/', + failureFlash: true + }), + function (req, res) { + res.redirect('/'); + } + ); + + app.get('/logout', function (req, res) { + if (req.user == null) { + return res.redirect('/'); + } + + req.user.nameID = req.user.id; + req.user.nameIDFormat = req.user.idFormat; + return samlStrategy.logout(req, function(err, uri) { + req.logout(); + + if ( req.session ) { + req.session.destroy((err) => { + if(err) { + return console.log(err); + } + }); + } + + return res.redirect(uri); + }); + + }); + + // to generate Service Provider's XML metadata + app.get('/saml/metadata', + function(req, res) { + res.type('application/xml'); + var spMetadata = samlStrategy.generateServiceProviderMetadata(fs.readFileSync(__dirname + '/cert/cert.pem', 'utf8')); + res.status(200).send(spMetadata); + } + ); + +}; \ No newline at end of file diff --git a/server.js b/server.js index ad1eadce71ef4991557637fcf4221cf61838ffa6..933dc17ab17a6c58ee294d2dc8b36551b2ff09f3 100644 --- a/server.js +++ b/server.js @@ -7,8 +7,43 @@ app.use(bodyParser.urlencoded({ extended: false })) app.use(bodyParser.json()) const request = require('ajax-request'); -app.use(express.static('vcm')); -app.listen(process.env.PORT || 8081); +const passport = require('passport') +const session = require('express-session') + +var env = process.env.NODE_ENV || 'development'; +const config = require('./config/config')[env]; + +app.set('views', 'vcm') +app.set('view engine', 'pug') +app.get('/index', function (req, res) { + console.log("does this works?") + if (req.isAuthenticated()) { + res.render('index', { + userLogin: true + }) + } else { + res.render('index', { + userLogin: false, + title: 'Hey', + message: 'Hello there!' + }) + } +}) +app.get('/index.html', function (req, res) { + res.redirect('/index') +}) + +app.use(express.static('vcm')); +app.use(session({ + resave: true, + saveUninitialized: true, + secret: 'thisisasecret-m4lab-tv3' + }) +) +app.use(passport.initialize()) +app.use(passport.session()) +require('./config/routes')(app, config, passport) +app.listen(process.env.PORT || 8081) \ No newline at end of file diff --git a/vcm/index.pug b/vcm/index.pug new file mode 100644 index 0000000000000000000000000000000000000000..d0035205854bd7b5534f0b1de493b887e813b51d --- /dev/null +++ b/vcm/index.pug @@ -0,0 +1,499 @@ +doctype html +head + meta(http-equiv='X-UA-Compatible' content='IE=edge') + meta(charset='utf-8') + meta(name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no') + title M4_Lab Platform + meta(name='description' content='Möchten Sie Ihre massiven Geodaten, z.B. 3D-Stadtmodell, Schrägluftbilder oder Punktwolken als gehostete Webkarte veröffentlichen?') + meta(name='keywords' content='digital@bw, SmartVillages, WebGIS, 3D-Stadtmodell, CityGML, virtualcityMAP, virtualcitySYSTEMS') + meta(name='author' content='virtualcitySYSTEMS') + meta(name='publisher' content='Landesamt für Geoinformation und Landentwicklung Baden-Württemberg') + meta(name='copyright' content='Landesamt für Geoinformation und Landentwicklung Baden-Württemberg') + meta(name='robots' content='index,follow') + meta(name='page-topic' content='Dienstleistung') + meta(name='page-type' content='company') + meta(http-equiv='language' content='deutsch, de') + meta(name='date' content='2017') + meta(name='audience' content='alle') + // favicon + link(rel='shortcut icon' href='images/favicon.ico') + meta(name='theme-color' content='#ffffff') + // Social Media Tags + meta(property='og:locale' content='de_DE') + meta(property='og:type' content='company') + meta(property='og:title' content='virtualcityMAP - 3D-Stadtmodelle im Browser') + meta(property='og:description' content='3D-Stadtmodelle im Browser - Entscheiden Sie sich für WebGIS Lösungen von virtualcitySYSTEMS.') + meta(property='og:url' content='https://www.virtualcitysystems.de') + meta(property='og:site_name' content='virtualcitySYSTEMS') + meta(property='article:tag' content='Berlin') + meta(property='article:tag' content='WebGIS') + meta(property='article:tag' content='3D-Stadtmodell') + meta(property='article:tag' content='CityGML') + meta(property='article:tag' content='Open Data') + meta(property='article:tag' content='Cesium') + meta(property='article:tag' content='SmartCities') + meta(property='article:section' content='company') + meta(property='article:section' content='city') + meta(property='article:published_time' content='2017-01-01T10:10:10+00:00') + meta(property='og:image' content='http://www.virtualcitysystems.de/images/vcs/slider/virtualcitySYSTEMS_Webhosting_Silder.jpg') + meta(name='twitter:title' content='virtualcityMAP - 3D-Stadtmodelle im Browser') + meta(name='twitter:image' content='http://www.virtualcitysystems.de/images/vcs/slider/virtualcitySYSTEMS_Webhosting_Silder.jpg') + meta(name='twitter:site' content='@virtualcity') + meta(name='twitter:card' content='summary') + style. + .login-logo{ + background-image:url("images/digital.png"); + background-size: contain; + background-repeat: no-repeat; + display: inline-block; + float: left; + width: 180px; + height: 60px; + } + .screen-bkgr{ + background-image:url("images/backgrd.png"); + background-size: cover; + background-repeat: repeat; + position:absolute; + top:0; + left:0; + right:0; + bottom:0; + text-align:center; + font-family:Arial, sans-serif; + font-size:1rem; + } + .login-header{ + position: absolute; + top: 0; + left: 0; + right: 0; + height: 60px; + padding: 10px; + background-color: rgba(255,255,255,0.9); + } + .login-header h2{ + color: #000000; + line-height: 1rem; + display: inline-block; + } + .login-header-links{ + display: inline-block; + float: right; + } + .login-header-links a{ + color: #000000; + text-decoration: none; + } + .login-content-wrap{ + position: absolute; + top: 80px; + left: 0; + right: 0; + bottom: 50px; + overflow-y: auto; + } + .login-content{ + display: inline-block; + width: 60%; + margin-top: 40px; + background-color: #ffffff; + text-align: left; + opacity: 0.9; + } + .login-content-header{ + background-color: #c9c9c9; + padding: 10px; + } + .login-content-form{ + padding: 10px; + opacity: 0.8; + } + .login-content-form li{ + line-height: 1.5rem; + } + .login-button{ + display: inline-block; + padding: 5px 10px; + border: 1 px #000000; + color: #000000; + font-weight: bold; + font-size: 18px; + background-color: #F7E819; + } + .login-footer{ + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 50px; + background-color: #8f1a1a; + text-align: right; + } + .login-footer a{ + color: #ffffff; + text-decoration: none; + font-size: .9rem; + margin: 20px 10px 0 0; + display: inline-block; + } + link(rel='stylesheet' href='css/vcm_ui.css') + link(rel='stylesheet' href='css/vcm.css') + link(rel='stylesheet' href='css/collapse.css') + // // added Story + link(rel='stylesheet' href='templates/custom.css') + link(rel='stylesheet' href='templates/story/story.css') + link(rel='stylesheet' href='templates/cus_Menu.css') +header.tour-header.vcm-header-height.vcm-header-base.vcm-border-splash + #header + .logo-box.vcm_copyright_headerLogoBox + .company-logo + .title-box.vcm_copyright_headerTitle + // Drop down menu starts here + .dropdown.hidden(style='float: right; right:20px') + i#dropdownMenu.fa.fa-bars(style='font-size:1.8rem;color: antiquewhite; margin-top:1rem;') + .dropdown-content + button.accordion Partizipation + .sub-menu + a(href='#' onclick="showtourSpecific('menu')") Böckingerstraße + button.accordion Energy + .sub-menu + a(href='#' onclick="EnergiekonzeptFunction('nothing')") Stöckach + button.accordion Acoustics + .sub-menu + a(href='#') Sub Menu 3 + button.accordion Mobility + .sub-menu + a(href='#') Sub Menu 3 + // Drop down menu ends here + .tool-box(style='cursor:pointer') +#story-frame.startscreen.vcm-map-top + // Content Start Screen + #balloon-startscreen.balloon.teaser-balloon + .balloon-content + h1.balloon-title.i18n_balloon_startscreen_title + // img src="images/Logo_SV.png" width="150" + strong M4_Lab + br + | Platform + // SSO experiment + if userLogin == true + button#tourstart-btn.buttonset.one(onclick='stopStory()') + span.i18n_balloon_startscreen_btn Start + else + button + span.i18n_balloon_startscreen_btn Login + .dialog-image-balloon + .balloon-left-edge + // End of: Content Start Screen + // Content Tour + #tour-frame(style='display: none; overflow-y: scroll;') + .tour-top-navi(style='z-index:99') + a#testing.top-nav.buttonset.one(href='#' onclick='goHome()') + i.fa.fa-home + | Home + // + Projekt 2 + Projekt 3 + Back to Projekt View 3 + // + Buttonleiste oben + Viewpoint + Hiding + Higlighting + Planning + Layer Switch + Labels + POI + Rotate + + // + Projekt 1 + ======================================================================================================= + #projektOne.SideInfo(style='display:none;') + h1#headOne.sticky Böckinger Straße + p.contentOne + | Die Reduzierung des privaten Wohnraums bedingt auch das Zusammenleben + | im Quartier. Wohnfunktionen werden wieder in den öffentlichen Raum + | und die Gemeinschaft verlagert und im Sinne von urbanen Gemeingütern + | genutzt. Die Funktionsweise solcher Gemeingüter beruht dabei hauptsächlich + | auf drei Grundelementen: der Ressource, einer Gruppe, die die Ressource + | gemeinsam nutzt und den Regeln, die diese Gruppe zur Nutzung + | festlegt. Aber wie kann man solche Gemeingüter in einem sich neu + | entwickelnden Quartier implementieren? + p.contentOne + | In einem Realexperiment werden Konzepte und Ideen in Verknüpfung mit + | lokalen Akteuren erarbeitet und ausprobiert. + br + | Der Garten des Imanuel Grözinger Hauses dient dabei als Ausgangspunkt. Drei Teams - Kommunikation, + | Programm und Bau - führen Interviews, erarbeiten ein Programm + | und eine bauliche Intervention vor Ort. Den Abschluss bildet ein Aktionstag + | gemeinsam mit Bewohnern und Nachbarn. + br + p.contentOne + | Folgen Sie uns auf Instagram! Fotos und Videos führen Sie durch unsere + | gesamte Woche in der Böckinger Straße. + br + p @les_stuttgart + p #ibasummerschool2019 #howtocommons #experiment + // Slideshow container + .slideshow-container + // Full-width images with number and caption text + .mySlides1.fade + .numbertext 1 / 17 + img(src='../../images/content/contentboeckingerstrasse/grafik_aufgabenstellung.jpg' style='width:100%') + .text Grafik + .mySlides1.fade + .numbertext 2 / 17 + img(src='../../images/content/contentboeckingerstrasse/boeckinger_strasse.jpg' style='width:100%') + .text Böckinger Straße + .mySlides1.fade + .numbertext 3 / 17 + img(src='../../images/content/contentboeckingerstrasse/holzwerkstatt_igh.jpg' style='width:100%') + .text Holzwerkstatt + .mySlides1.fade + .numbertext 4 / 17 + img(src='../../images/content/contentboeckingerstrasse/infoabend_garten_igh.jpg' style='width:100%') + .text Infoabend im Garten + .mySlides1.fade + .numbertext 5 / 17 + img(src='../../images/content/contentboeckingerstrasse/interviews_nachbarschaft.jpg' style='width:100%') + .text Interviews in der Nachbarschaft + .mySlides1.fade + .numbertext 6 / 17 + img(src='../../images/content/contentboeckingerstrasse/offene_bauwerkstatt_1.jpg' style='width:100%') + .text Offene Bauwerkstatt + .mySlides1.fade + .numbertext 7 / 17 + img(src='../../images/content/contentboeckingerstrasse/offene_bauwerkstatt_2.jpg' style='width:100%') + .text Offene Bauwerkstatt + .mySlides1.fade + .numbertext 8 / 17 + img(src='../../images/content/contentboeckingerstrasse/offene_bauwerkstatt_3.jpg' style='width:100%') + .text Offene Bauwerkstatt + .mySlides1.fade + .numbertext 9 / 17 + img(src='../../images/content/contentboeckingerstrasse/planungsgebiet_choreographie.jpg' style='width:100%') + .text Planungsgebiet Choreographie + .mySlides1.fade + .numbertext 10 / 17 + img(src='../../images/content/contentboeckingerstrasse/planungsgebiet_vogelperspektive.jpg' style='width:100%') + .text Planungsgebiet Vogelperspektive + .mySlides1.fade + .numbertext 11 / 17 + img(src='../../images/content/contentboeckingerstrasse/station1_spielekiosk.jpg' style='width:100%') + .text Spielekiosk + .mySlides1.fade + .numbertext 12 / 17 + img(src='../../images/content/contentboeckingerstrasse/station2_gartenkiosk.jpg' style='width:100%') + .text Gartenkiosk + .mySlides1.fade + .numbertext 13 / 17 + img(src='../../images/content/contentboeckingerstrasse/station3_outdoorkiosk.jpg' style='width:100%') + .text Outdoorkiosk + .mySlides1.fade + .numbertext 14 / 17 + img(src='../../images/content/contentboeckingerstrasse/station3_outdoorkiosk1.jpg' style='width:100%') + .text Outdoorkiosk + .mySlides1.fade + .numbertext 15 / 17 + img(src='../../images/content/contentboeckingerstrasse/station4_infokiosk.jpg' style='width:100%') + .text Infokiosk + .mySlides1.fade + .numbertext 16 / 17 + img(src='../../images/content/contentboeckingerstrasse/workshop_cafe_tas_1.jpg' style='width:100%') + .text Workshop Cafe Tas + .mySlides1.fade + .numbertext 17 / 17 + img(src='../../images/content/contentboeckingerstrasse/workshop_cafe_tas_2.jpg' style='width:100%') + .text Workshop Cafe Tas + // Next and previous buttons + a.prev(onclick='plusSlides(-1, 0)') ❮ + a.next(onclick='plusSlides(1, 0)') ❯ + br + // The dots/circles + div(style='text-align:center') + span.dot(onclick='currentSlide(1)') + span.dot(onclick='currentSlide(2)') + span.dot(onclick='currentSlide(3)') + span.dot(onclick='currentSlide(4)') + span.dot(onclick='currentSlide(5)') + span.dot(onclick='currentSlide(6)') + span.dot(onclick='currentSlide(7)') + span.dot(onclick='currentSlide(8)') + span.dot(onclick='currentSlide(9)') + span.dot(onclick='currentSlide(10)') + span.dot(onclick='currentSlide(11)') + span.dot(onclick='currentSlide(12)') + span.dot(onclick='currentSlide(13)') + span.dot(onclick='currentSlide(14)') + span.dot(onclick='currentSlide(15)') + span.dot(onclick='currentSlide(16)') + span.dot(onclick='currentSlide(17)') + p.contentOne + strong TEAM KOMMUNIKATION + | arbeitet direkt mit den Anwohnern zusammen. + | Wer sind relevante Akteure? Welches Potential bringen neue Akteure mit? + | Welche Art der Kommunikation braucht es? In Interviews werden Bedürfnisse + | und Wünsche für das zukünftige Quartier abgefragt und gemeinsam + | eine Kommunikationsstrategie erarbeitet. + br + strong TEAM PROGRAMM + | beschäftigt sich damit, wie man die gegenwärtigen und + | zukünftigen Bewohner*innen des Quartiers aktivieren kann, Gemeingüter + | zu entwickeln und zu nutzen. Welche Aktivitäten gibt es bereits vor Ort? + | Wo finden sie statt? Und durch welches Programm kann man Akteure + | zusammen bringen? + br + strong TEAM BAU + | gestaltet eine bauliche Intervention, die von den Nachbarn + | gemeinschaftlich im Sinne eines Urban Common genutzt werden kann. + | Was fehlt noch? Welche bauliche Intervention kann die Bildung von urban + | commons unterstützen? Und was bleibt am Ende zurück? + #UmfrageOne.SideInfo(style='display:none;') + iframe(style='width: 95%; height:35em;margin-left:1em;margin-right:1em;border: none;' src='https://umfrage.smartvillages.online/limesurvey/index.php/351963?lang=de-informal') + p.contentOne + | Die Reduzierung des privaten Wohnraums bedingt auch das Zusammenleben + | im Quartier. Wohnfunktionen werden wieder in den öffentlichen Raum + | und die Gemeinschaft verlagert und im Sinne von urbanen Gemeingütern + | genutzt. Die Funktionsweise solcher Gemeingüter beruht dabei hauptsächlich + | auf drei Grundelementen: der Ressource, einer Gruppe, die die Ressource + | gemeinsam nutzt und den Regeln, die diese Gruppe zur Nutzung + | festlegt. Aber wie kann man solche Gemeingüter in einem sich neu + | entwickelnden Quartier implementieren? + p.contentOne + | In einem Realexperiment werden Konzepte und Ideen in Verknüpfung mit + | lokalen Akteuren erarbeitet und ausprobiert. + br + | Der Garten des Imanuel Grözinger Hauses dient dabei als Ausgangspunkt. Drei Teams - Kommunikation, + | Programm und Bau - führen Interviews, erarbeiten ein Programm + | und eine bauliche Intervention vor Ort. Den Abschluss bildet ein Aktionstag + | gemeinsam mit Bewohnern und Nachbarn. + br + p.contentOne + | Folgen Sie uns auf Instagram! Fotos und Videos führen Sie durch unsere + | gesamte Woche in der Böckinger Straße. + br + p @les_stuttgart + p #ibasummerschool2019 #howtocommons #experiment + // ======================================================================================================= + // Project Stoeckach Energiekonzept + #Energiekonzept.SideInfo(style='display:none;') + h1#headOne.sticky Energy Project Stöckach + p.contentOne + | In this study, we have evaluated multiple local energy system scenarios to find the optimal energy system design concepts for the” future” EnBW-Areal. In this study, + br + | • we developed a 3D CityGML model for the EnBW-Areal and along with other calculation tools, estimated the electricity, heat, and hot water related energy demand profiles for the neighborhood. + br + | • we evaluated multiple energy supply options that includes energy sources and conversion technologies to meet the estimated total energy demand. + br + | • we evaluated the cost minimized technology mixes that achieves reduced CO2 emissions and compared the different energy system scenarios against a baseline energy system. + button#energydemand.collapsible(onclick="highlightFeatures('energydemand')" type='button') Energy demand + .content + p + | The annual electrical, heating, and hot water energy demand for the EnBW-Areal is estimated to be 2.88 GWh, 1.57 GWh, and 1.77 GWh, respectively. + .slideshow-container + // Full-width images with number and caption text + .mySlides2.fade + .numbertext 1 / 4 + img(src='../../images/content/contentstoeckach/img1.jpg' style='width:100%') + .text The estimated hourly heat energy demand (units: kW) + .mySlides2.fade + .numbertext 2 / 4 + img(src='../../images/content/contentstoeckach/img2.jpg' style='width:100%') + .text The estimated hourly energy demand for hot water generation (units: kW) + .mySlides2.fade + .numbertext 3 / 4 + img(src='../../images/content/contentstoeckach/img3.jpg' style='width:100%') + .text Electricity demand for non-residential spaces (units: kW) + .mySlides2.fade + .numbertext 4 / 4 + img(src='../../images/content/contentstoeckach/img4.jpg' style='width:100%') + .text Electricity demand for residential and spaces (units: kW) + // Next and previous buttons + a.prev(onclick='plusSlides(-1, 1)') ❮ + a.next(onclick='plusSlides(1, 1)') ❯ + br + // The dots/circles + div(style='text-align:center') + span.dot(onclick='currentSlide(1)') + span.dot(onclick='currentSlide(2)') + span.dot(onclick='currentSlide(3)') + span.dot(onclick='currentSlide(4)') + button#solarpotential.collapsible(onclick="highlightFeatures('solarpotential')" type='button') Solar PV potential + .content + p + | The study shows that the EnBW-Areal has a feasible potential to utilize approx. 30-35% of the roof area to generate local electricity from solar PV. As a result, the energy consumption related CO2 emissions can be reduced by about 30% compared to the base scenario evaluated in this study at an 8% less cost. PV curtailment due to over production and feed-in constraints could lower the share of integrated PV generation significantly above 35% penetration levels. There are both technological and market-based strategies to optimally integrate the local PV generation. However, such concepts must be analyzed further in greater detail. + button#heatpump.collapsible(onclick="highlightFeatures('heatpump')" type='button') Power-to-heat via heat pump + .content + p + | High-efficient heat pumps can both reduce the CO2 emissions and the primary energy use. A direct comparison between the heat pumps and district heating is tricky because the emissions from a district heating plant heavily depends on it’s fuel mix. In Stuttgart, it is common to use a fuel mix comprising of coal, gas, and municipal waste to generate heat. + br + | It is more economically feasible to schedule the heat pump operation to supply the base-load heating and hot water demand. That increases the utilization of heat pump capacity, and therefore the rate of return on the investment. + br + | Thermal storages improve the utilization of heat pump capacity. The flexibility of thermal storage units to meet the peak demand enable the heat pumps to be slightly undersized for the base-load operation. + br + .slideshow-container + // Full-width images with number and caption text + //
+ img(src='../../images/content/contentstoeckach/img5.jpg' style='width:100%; margin-bottom: 5em;') + .text(style='margin-top:0em;') + | The capacity of heat pump(s) is allocated to supply base-load heat demand. The valley points of heat pump operation are filled by thermal storage charging action to improve heat pump capacity utilization. + //
+ button#thermalstorage.collapsible(onclick="highlightFeatures('thermalstorage')" type='button') Thermal storage + .content + p + | Thermal storages improve the utilization of heat pump capacity. The flexibility of thermal storage units to meet the peak demand enable the heat pumps to be slightly undersized for the base-load operation. + button#batterystorage.collapsible(onclick="highlightFeatures('batterystorage')" type='button') Battery storage + .content + p + | The adoption of residential battery storages in Germany is driven by the self-consumption optimization objective. At lower PV levels, the generated PV electricity can be directly consumed, hence the benefits of battery systems are less. However, at higher PV penetration levels and when innovative market designs enable the participation of battery storage systems to provide other services to the electricity network, the value of battery storage systems can increase rapidly. + button#localEnergy.collapsible(onclick="highlightFeatures('energydemand')" type='button') Is local energy transition economically competitive? + .content + p + | The answer to this question has two layers. The first layer is the aggregated system level feasibility, which is what we can see from our study. The second layer is the benefit distribution and economic feasibility at the individual prosumer level that is something that requires much deeper analysis. + br + | We see at the system level; the local energy transition has a positive outlook. Some of the scenarios that we looked at recovered their total investment within the first 8 years. + br + .slideshow-container + // Full-width images with number and caption text + //
+ img(src='../../images/content/contentstoeckach/img6.jpg' style='width:100%; margin-bottom: 4em;') + .text(style='margin-top:0em;') + | Comparison of the return of investment in each scenario until the breakeven point compared to the base scenario (units: EUR) + //
+ #tour-button(title='Karte/Story umschalten') + i.fa + // End of: Content Tour +#vcs_map_container +// + div id="vcs_map_container"> +
+
virtualcityMAP
+
+ + vcs.vcm.Framework.activateLogging(); + vcs.vcm.Framework.loadConfig('config.json'); +