Skip to content

Commit 2e5f437

Browse files
authored
Merge pull request #708 from Martin-Gleiss/develop
Release v3.2.1
2 parents 67e67b0 + 8b8a11e commit 2e5f437

29 files changed

+470
-537
lines changed

changelog.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,38 @@
1+
## 3.2.1
2+
### New / Changed Widgets
3+
4+
### Other New Features
5+
- page "driver_debug" for visualizing communication parameters. Good if browser tools are not available, e.g. on smartphones
6+
- phone widget widget displays callees image on outgoing calls and accepts images also with callers / callees names
7+
8+
### Improvements
9+
- docu for image displaying widgets improved (multimedia.widget, basic.print)
10+
- basic.windows takes 'closed', 'tilted' and 'open' as arguments, as frequently used in fhem. example3.graphic widgets also updated.
11+
12+
### Updated Libraries
13+
14+
### Deprecated
15+
16+
### Removed Features
17+
18+
### Fixed Bugs
19+
- menu item "smarthomeNG" got lost if new smarthomeNG driver was selected
20+
- calendars with names containing whitespaces were not loaded (since at least v2.9)
21+
- smarthomeNG new driver did not work on old browsers (javascript replaceAll() function not available)
22+
- mixing autogenerated pages from smarthomeNG with own pages did not work with the new smarthomeNG driver
23+
- menus in config page did not show as dialogs if screen was too small (e.g. split w/ browser tools)
24+
- config page did not work if ./dropins/lang folder was missing
25+
- cache folders were not created separately for different devices. This caused CSS mix if cache was activated and differnet designs were configured
26+
- on iOS9 the UZSU widgets did not run and even prevented smartVISU from starting if cache was activated
27+
- new smarthomeng.js driver did not work if a port was provided in the URL
28+
- device.uzsutable did not run on iOS9 devices (even after general uzsu fix)
29+
- offline driver stopped working on large number of items (php request overflow)
30+
- status.activelist did not work correctly if more than one status.activelist was on a page
31+
32+
### Known Bugs
33+
- if item contains a stringified number (e.g. with leading zero). widget.set converts it back to numeric format - so basic.print can not print it as text
34+
35+
136
## 3.2.0
237
### New / Changed Widgets
338
- basic.window and device.window provide an additional color mode: icon0 if closed / custom color if open

driver/io_offline.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,9 @@ var io = {
191191
},
192192

193193
/**
194-
* Reads all values from bus and refreshes the pages
194+
* Reads limited range of items in order to avoid php request overflow
195195
*/
196-
all: function () {
197-
var items = widget.listeners().join(',');
198-
196+
getSlice: function(items) {
199197
// only if anyone listens
200198
if (items.length) {
201199
$.ajax({ url: 'driver/io_offline.php',
@@ -218,6 +216,19 @@ var io = {
218216
})
219217
.fail(notify.json)
220218
}
219+
},
220+
221+
/**
222+
* Reads all values from bus and refreshes the pages
223+
*/
224+
all: function() {
225+
var allItems = widget.listeners();
226+
var items;
227+
228+
do {
229+
items = allItems.splice(0,100).join(',');
230+
io.getSlice(items);
231+
} while (allItems.length > 0);
221232

222233
// plots
223234
var repeatSeries = function(item, tmin, tmax, ymin, ymax, cnt, step, startval) {

driver/io_smarthomeng.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* @default driver_port 2424
1212
* @default driver_tlsport 2425
1313
* @hide reverseproxy
14-
* @hide driver_realtime
14+
* @hide driver_realtime
1515
* @hide driver_ssl
1616
* @hide driver_username
1717
* @hide driver_password
@@ -74,8 +74,8 @@ var io = {
7474

7575
// if user-called host is not an IP v4 address check if called host is internal hostname of smartVISU server
7676
// otherwise assume that call comes from external and then empty io.address
77-
if (!$.isNumeric(location.host.replaceAll('.',''))){
78-
if ( location.host != sv.config.svHostname )
77+
if (!$.isNumeric(location.hostname.split('.').join(''))) { // replaceAll() does not work for old browsers
78+
if ( location.hostname != sv.config.svHostname )
7979
io.address = '';
8080
}
8181
io.open();
@@ -140,9 +140,9 @@ var io = {
140140
// use url of current page if not defined
141141
io.address = location.hostname;
142142
}
143-
io.port = ports[protocol];
143+
io.port = ports[protocol];
144144

145-
if (!io.port) {
145+
if (!io.port) { // is still undefined, if io.address was empty at start of io.open
146146
// use port of current page if not defined and needed
147147
if (location.port != '') {
148148
io.port = location.port;
@@ -157,7 +157,7 @@ var io = {
157157
io.port = ports[io.address.substr(0, io.address.indexOf(':'))+'://'];
158158
}
159159
// DEBUG:
160-
console.log("[io.smarthome.py] opening websocket on "+ protocol + io.address + ':' + io.port);
160+
console.log("[io.smarthomeng] opening websocket on "+ protocol + io.address + ':' + io.port);
161161
io.socket = new WebSocket(protocol + io.address + ':' + io.port);
162162

163163
io.socket.onopen = function () {
@@ -178,7 +178,7 @@ var io = {
178178
var item, val;
179179
var data = JSON.parse(event.data);
180180
// DEBUG:
181-
console.log("[io.smarthome.py] receiving data: ", event.data);
181+
console.log("[io.smarthomeng] receiving data: ", event.data);
182182

183183
switch (data.cmd) {
184184
case 'item':
@@ -248,11 +248,11 @@ var io = {
248248

249249
io.socket.onerror = function (error) {
250250
if(io.socketErrorNotification == null || !notify.exists(io.socketErrorNotification))
251-
io.socketErrorNotification = notify.message('error', 'Driver: smarthome.py', 'Could not connect to smarthome.py server!<br /> Websocket error ' + error.data + '.');
251+
io.socketErrorNotification = notify.message('error', 'Driver: smarthomeng', 'Could not connect to smarthomeNG server!<br /> Websocket error ' + error.data + '.');
252252
};
253253

254254
io.socket.onclose = function () {
255-
console.log('[io_smarthome.py]: Connection closed to smarthome.py server!');
255+
console.log('[io_smarthomeng]: Connection closed to smarthomeNG server!');
256256
};
257257
},
258258

@@ -263,11 +263,11 @@ var io = {
263263
if (io.socket.readyState == 1) {
264264
io.socket.send(unescape(encodeURIComponent(JSON.stringify(data))));
265265
// DEBUG:
266-
console.log('[io.smarthome.py] sending data: ', JSON.stringify(data));
266+
console.log('[io.smarthomeng] sending data: ', JSON.stringify(data));
267267
}
268268
else {
269269
// DEBUG:
270-
console.log('[io.smarthome.py] web socket not ready: ', JSON.stringify(data));
270+
console.log('[io.smarthomeng] web socket not ready: ', JSON.stringify(data));
271271
if (data.cmd == 'logic') io.triggerqueue.push(JSON.stringify(data));
272272
};
273273
},
@@ -298,7 +298,7 @@ var io = {
298298
sendqueue: function () {
299299
while (io.triggerqueue.length > 0) {
300300
// DEBUG:
301-
console.log('[io.smarthome.py] send from queue: ', io.triggerqueue[0]);
301+
console.log('[io.smarthomeng] send from queue: ', io.triggerqueue[0]);
302302
io.socket.send(io.triggerqueue.shift());
303303
}
304304
},
@@ -342,7 +342,7 @@ var io = {
342342
* Closes the connection
343343
*/
344344
close: function () {
345-
console.log("[io.smarthome.py] close connection");
345+
console.log("[io.smarthomeng] close connection");
346346

347347
if (io.socket.readyState > 0) {
348348
io.socket.close();

index.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757

5858
// add smarthome dir if it is not directly chosen.
5959
// allows combination of custom pages with auto-generated pages from smarthomeNG
60-
if (config_driver == 'smarthome.py' and $actual_pages != 'smarthome' and is_dir(const_path."pages/smarthome"))
60+
if (substr(config_driver, 0, 9) == 'smarthome' and $actual_pages != 'smarthome' and is_dir(const_path."pages/smarthome"))
6161
$loader->addPath(const_path.'pages/smarthome');
6262

6363
// make sure SV doesn't load stuff from dropins unless pages are configured

lib/base/base.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1795,7 +1795,7 @@ $(document).on('pagecontainerchange', function(event, ui) {
17951795
.end().each(function(){ // block browser back / foreward buttons
17961796
var currentURL = $(this).context.baseURI;
17971797
$(document).on("pagecontainerbeforechange", function (e, data) {
1798-
if (typeof data.toPage == "string" && data.prevPage != undefined ) {
1798+
if (typeof data.toPage == "string" && data.prevPage != undefined && data.options.role != "popup" && data.options.role != "dialog" && data.options.direction != "back") {
17991799
data.toPage = currentURL;
18001800
history.pushState(null,'',currentURL);
18011801
console.log(currentURL + ': clear history in order to block the back / forward buttons');

lib/calendar/calendar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public function init($request)
4141
if(isset($request['count']))
4242
$this->count = $request['count'];
4343
if(isset($request['calendar']))
44-
$this->calendar_names = preg_split('/[\s,]+/m', strtolower($request['calendar']));
44+
$this->calendar_names = preg_split('/,\s/m', strtolower($request['calendar']));
4545
$this->url = config_calendar_url;
4646
}
4747

lib/config.php

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,6 @@ public function get($source = 'all')
5353
case 'globalonly':
5454
if (is_file(const_path.'config.ini'))
5555
$config = parse_ini_file(const_path.'config.ini', true, self::INI_SCANNER);
56-
57-
//drop support for legacy config.php as of v3.1
58-
//
59-
//elseif (is_file(const_path.'config.php')) {
60-
// read legacy config.php
61-
// $configphp = file_get_contents(const_path.'config.php');
62-
// preg_match_all("/define\s*\s*\('config_(.*?)'\s*,\s*(.*)\s*\)\s*;\s*[\r\n]+/", $configphp, $matches, PREG_SET_ORDER);
63-
64-
// $config = array();
65-
// foreach($matches as $match) {
66-
// $config[$match[1]] = eval('return '.$match[2].';');
67-
// }
68-
//}
6956
break;
7057

7158
// configuration per pages (config.ini in current pages folder)
@@ -124,18 +111,19 @@ public function save($target, $options, $pages) {
124111
break;
125112
case 'cookie':
126113
$basepath = substr(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), 0, -strlen(substr($_SERVER['SCRIPT_FILENAME'], strlen(const_path))));
127-
if (isset($config['cache'])) {
128-
// generate unique cache folder for cookie (combination of remote IP, forwarded IP and time should be unique)
129-
if(!isset($config['cachefolder']) || $config['cachefolder'] == 'global')
130-
$config['cachefolder'] = md5($_SERVER['REMOTE_ADDR'] . ($_SERVER['HTTP_CLIENT_IP'] ?: $_SERVER['HTTP_X_FORWARDED_FOR'] ?: $_SERVER['HTTP_X_FORWARDED'] ?: $_SERVER['HTTP_FORWARDED_FOR'] ?: $_SERVER['HTTP_FORWARDED']) . time());
131-
} else
132-
unset($config['cachefolder']);
133-
114+
134115
if(count($config) > 0){ // some options are set
135116
foreach ($config as $key=>&$val) {
136117
$val = ($val == "true") ? "1" : $val;
137118
$val = ($val == "false") ? "" : $val;
138119
}
120+
// generate unique cache folder for cookie (combination of remote IP, forwarded IP and time should be unique) - in case cache is activated globally
121+
if(!isset($config['cachefolder']) || $config['cachefolder'] == 'global'){
122+
$clientIP = (((((isset($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP'] ? $_SERVER['HTTP_CLIENT_IP']: isset($_SERVER['HTTP_X_FORWARDED_FOR']) &&$_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] :
123+
isset($_SERVER['HTTP_X_FORWARDED']) && $_SERVER['HTTP_X_FORWARDED']) ? $_SERVER['HTTP_X_FORWARDED']: isset($_SERVER['HTTP_FORWARDED_FOR']) && $_SERVER['HTTP_FORWARDED_FOR']) ? $_SERVER['HTTP_FORWARDED_FOR'] :
124+
isset($_SERVER['HTTP_FORWARDED']) && $_SERVER['HTTP_FORWARDED']) ? $_SERVER['HTTP_FORWARDED']:'');
125+
$config['cachefolder'] = md5($_SERVER['REMOTE_ADDR'] . $clientIP . time());
126+
}
139127
$confexpire = time()+3600*24*364*10; // expires after 10 years
140128
$success = setcookie('config', json_encode($config), ['expires' => $confexpire, 'path' => $basepath, 'samesite' => 'Lax']);
141129
}

lib/phone/phone.php

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,6 @@ public function prepare()
5050
{
5151
// date
5252
$ds['date'] = transdate('short', strtotime($ds['date']));
53-
54-
// is there a picture to the caller?
55-
if ($ds['number'] != '' and is_file(const_path.'pics/phone/'.$ds['number'].'.jpg'))
56-
$ds['pic'] = $ds['number'].'.jpg';
57-
elseif ($ds['number'] != '' and is_file(const_path.'pics/phone/'.$ds['number'].'.png'))
58-
$ds['pic'] = $ds['number'].'.png';
59-
else
60-
$ds['pic'] = '0.jpg';
61-
6253
$ds['text'] = $ds['name'];
6354

6455
// no name? caller unknown
@@ -95,6 +86,17 @@ public function prepare()
9586
if ($ds['called'] !='')
9687
$ds['number'] = $ds['called'];
9788
}
89+
// is there a picture to the caller?
90+
if ($ds['number'] != '' and is_file(const_path.'pics/phone/'.$ds['number'].'.jpg'))
91+
$ds['pic'] = $ds['number'].'.jpg';
92+
elseif ($ds['number'] != '' and is_file(const_path.'pics/phone/'.$ds['number'].'.png'))
93+
$ds['pic'] = $ds['number'].'.png';
94+
elseif ($ds['name'] != '' and is_file(const_path.'pics/phone/'.$ds['name'].'.jpg'))
95+
$ds['pic'] = $ds['name'].'.jpg';
96+
elseif ($ds['name'] != '' and is_file(const_path.'pics/phone/'.$ds['name'].'.png'))
97+
$ds['pic'] = $ds['name'].'.png';
98+
else
99+
$ds['pic'] = '0.jpg';
98100

99101
$ret[] = $ds;
100102
}

pages/base/config.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ <h3>{{ lang('configuration_page', 'interface', 'label') }}</h3>
6161
]
6262
) }}
6363
{{ forms.config_input(source, values, 'title') }}
64-
{{ forms.config_select(source, values, 'lang', dir('lang', '^(.*?)\.ini$')|merge(dir('dropins/lang', '^(.*?)\.ini$')) ) }}
64+
{% set langdir = dir('lang', '^(.*?)\.ini$') %} {% if isdir('dropins/lang') %} {% set langdir = langdir|merge(dir('dropins/lang', '^(.*?)\.ini$')) %} {% endif %}
65+
{{ forms.config_select(source, values, 'lang', langdir ) }}
6566
{{ forms.config_flip(source, values, 'cache', '<button type="button" data-theme="a" data-icon="delete" data-inline="true" id="clear_cache' ~ id ~ '" class="ui-micro"' ~ (not values[source]['cache'] is defined ? ' disabled="disabled"'|raw) ~ '>' ~ lang('configuration_page', 'cache', 'clearbutton') ~'</button>') }}
6667
{{ forms.check_cache ( source, values, 'cache') }}
6768
</div>

pages/base/driver_debug.html

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* -----------------------------------------------------------------------------
3+
* @package smartVISU
4+
* @author Wolfram v. Hülsen
5+
* @copyright 2022
6+
* @license GPL [http://www.gnu.de]
7+
* -----------------------------------------------------------------------------
8+
*/
9+
10+
/** visualizes the most relevant parameters of the websocekt connection
11+
* good e.g. on smartphones where no browser console is available
12+
*/
13+
14+
{% extends "rooms.html" %}
15+
16+
{% block content %}
17+
<h1>Display Connection Details</h1>
18+
19+
<h2>Configuration Parameters</h2>
20+
<ul>
21+
<li>driver name:&nbsp;&nbsp; <span id="line1"></span></li>
22+
<li>sv.driver.address:&nbsp;&nbsp;<span id="line2"></span></li>
23+
<li>sv.config.driver.port:&nbsp;&nbsp; <span id="line3"></span></li>
24+
<li>sv.config.driver.tlsport:&nbsp;&nbsp; <span id="line4"></span></li>
25+
<li>sv.config.svHostname:&nbsp;&nbsp; <span id="line5"></span></li>
26+
27+
</ul>
28+
<h2>Location Info</h2>
29+
<ul>
30+
<li>location.host:&nbsp;&nbsp; <span id="line6"></span></li>
31+
<li>location.hostname:&nbsp;&nbsp; <span id="line7"></span></li>
32+
<li>location.protocol:&nbsp;&nbsp;<span id="line8"></span></li>
33+
</ul>
34+
35+
<h2>Websocket Parameters</h2>
36+
<ul>
37+
<li>io.address:&nbsp;&nbsp; <span id="line9"></span></li>
38+
<li>io.port:&nbsp;&nbsp; <span id="line10"></span></li>
39+
<li>Websocket URL:&nbsp;&nbsp; <span id="line11"></span></li>
40+
</ul>
41+
42+
<span id="line12"></span><br />
43+
<span id="line13"></span><br />
44+
45+
<script>
46+
$('#line1').text(sv.config.driver.name);
47+
$('#line2').text(sv.config.driver.address);
48+
$('#line3').text(sv.config.driver.port);
49+
$('#line4').text(sv.config.driver.tlsport);
50+
$('#line5').text(sv.config.svHostname);
51+
$('#line6').text(location.host);
52+
$('#line7').text(location.hostname);
53+
$('#line8').text(location.protocol);
54+
$('#line9').text(io.address);
55+
$('#line10').text(io.port);
56+
$('#line11').text(io.socket.url);
57+
58+
</script>
59+
60+
61+
{% endblock %}

0 commit comments

Comments
 (0)