Skip to content

Commit

Permalink
Check subscription
Browse files Browse the repository at this point in the history
  • Loading branch information
GermanBluefox committed Oct 23, 2023
1 parent 419e6c3 commit 41d7100
Show file tree
Hide file tree
Showing 15 changed files with 324 additions and 129 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
### **WORK IN PROGRESS**
-->
## ToDo
- Dimmer
- Controller
- Devices
- Add device without room or function (by ID)
- Get login & pass from iot (new js-controller version) may be

## Changelog
### **WORK IN PROGRESS**
Expand Down
2 changes: 1 addition & 1 deletion io-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"native": {
"interface": "",
"login": "",
"password": ""
"pass": ""
},
"objects": [],
"instanceObjects": [
Expand Down
47 changes: 43 additions & 4 deletions src-admin/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import GenericApp from '@iobroker/adapter-react-v5/GenericApp';
import { I18n, Loader, AdminConnection } from '@iobroker/adapter-react-v5';

import ConfigHandler from './components/ConfigHandler';
import Devices from './components/Devices';
import Controller from './components/Controller';
import Bridges from './components/Bridges';
import Options from './components/Options';
import Options from './Tabs/Options';
import Controller from './Tabs/Controller';
import Bridges from './Tabs/Bridges';
import Devices from './Tabs/Devices';

const productIDs = [];
for (let i = 0x8000; i <= 0x801F; i++) {
Expand Down Expand Up @@ -235,6 +235,7 @@ class App extends GenericApp {
matter={this.state.matter}
updateConfig={this.onChanged}
showToast={text => this.showToast(text)}
checkLicenseOnAdd={type => this.checkLicenseOnAdd(type)}
/>;
}

Expand All @@ -250,9 +251,47 @@ class App extends GenericApp {
matter={this.state.matter}
updateConfig={this.onChanged}
showToast={text => this.showToast(text)}
checkLicenseOnAdd={() => this.checkLicenseOnAdd('addDevice')}
/>;
}

async getLicense() {
if (this.state.native.login && this.state.native.pass) {
if (this.state.alive) {
// ask the instance
const result = await this.socket.sendTo(`matter.${this.instance}`, 'getLicense', { login: this.state.native.login, pass: this.state.native.pass });
if (result.error) {
this.showToast(result.error);
return false;
}
return result.result;
}
this.showToast('You need a running matter instance to add more than one bridge or more than 2 devices');
return false;
}
return false;
}

async checkLicenseOnAdd(type) {
if (type === 'addBridge') {
if (this.state.matter.bridges.filter(bridge => bridge.enabled).length >= 1) {
return this.getLicense();
}
} else if (type === 'addDevice') {
if (this.state.matter.devices.filter(device => device.enabled).length >= 2) {
return this.getLicense();
}
} else if (type === 'addDeviceToBridge') {
if (this.state.matter.bridges.filter(bridge => bridge.enabled && bridge.list.filter(dev => dev.enabled).length >= 5)) {
return this.getLicense();
}
} else {
return false;
}

return true; // User may add one bridge or one device
}

onSave(isClose) {
super.onSave && super.onSave(isClose);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ class Bridges extends React.Component {
list: [],
uuid: uuidv4(),
});
this.props.updateConfig(matter)
this.props.updateConfig(matter);
}, 100);
}
}
Expand Down Expand Up @@ -378,7 +378,14 @@ class Bridges extends React.Component {
</TableCell>
</TableRow>
{data.connectionInfo.map((info, i) => <TableRow key={i}>
<TableCell>{info.vendor}{info.label ? <span style={{ opacity: 0.7, marginLeft: 8, fontStyle: 'italic' }}>({info.label})</span> : null}</TableCell>
<TableCell>
{info.vendor}
{info.label ? <span style={{ opacity: 0.7, marginLeft: 8, fontStyle: 'italic' }}>
(
{info.label}
)
</span> : null}
</TableCell>
<TableCell>
{info.connected ? <span style={{ color: 'green' }}>{I18n.t('Connected')}</span> : I18n.t('Not connected')}
</TableCell>
Expand Down Expand Up @@ -454,7 +461,7 @@ class Bridges extends React.Component {
type: 'device',
name: getText(device.name),
originalName: getText(device.name),
bridgeIndex: bridgeIndex,
bridgeIndex,
device: devIndex,
vendorID: false,
productID: false,
Expand Down Expand Up @@ -704,7 +711,7 @@ class Bridges extends React.Component {
type: 'bridge',
name: getText(bridge.name),
originalName: getText(bridge.name),
bridgeIndex: bridgeIndex,
bridgeIndex,
vendorID: bridge.vendorID,
originalVendorID: bridge.vendorID,
productID: bridge.productID,
Expand All @@ -721,9 +728,11 @@ class Bridges extends React.Component {
</Tooltip>
</TableCell>
<TableCell style={{ width: 0 }}>
<Tooltip title={bridge.enabled && !allowDisable ? I18n.t('At least one enabled bridge must exist') : I18n.t('Delete bridge')}>
<Tooltip
title={bridge.enabled && !allowDisable ? I18n.t('At least one enabled bridge must exist') : I18n.t('Delete bridge')}
>
<span>
<IconButton
<IconButton
disabled={bridge.enabled && !allowDisable}
onClick={e => {
e.stopPropagation();
Expand All @@ -750,17 +759,22 @@ class Bridges extends React.Component {
<TableCell style={{ border: 0, opacity: bridge.enabled ? 1 : 0.5 }}>
<b>{I18n.t('Devices')}</b>
<Tooltip title={I18n.t('Add device')}>
<IconButton onClick={() => this.setState(
{
<IconButton onClick={async () => {
const isLicenseOk = await this.props.checkLicenseOnAdd('addDeviceToBridge');
if (!isLicenseOk) {
this.props.alive && this.props.showToast('You need ioBroker.pro assistant or remote subscription to have more than 5 devices in bridge');
return;
}
this.setState({
dialog: {
type: 'bridge',
name: getText(bridge.name),
bridge: bridgeIndex,
devices: bridge.list,
addDevices: this.addDevicesToBridge,
},
},
)}
});
}}
>
<Add />
</IconButton>
Expand All @@ -781,7 +795,12 @@ class Bridges extends React.Component {
{this.renderDebugDialog()}
<Tooltip title={I18n.t('Add bridge')}>
<Fab
onClick={() => {
onClick={async () => {
const isLicenseOk = await this.props.checkLicenseOnAdd('addBridge');
if (!isLicenseOk) {
this.props.alive && this.props.showToast('You need ioBroker.pro assistant or remote subscription to have more than one bridge');
return;
}
let i = 1;
const name = `${I18n.t('New bridge')} `;
while (this.props.matter.bridges.find(b => b.name === name + i)) {
Expand Down Expand Up @@ -851,6 +870,7 @@ class Bridges extends React.Component {
}

Bridges.propTypes = {
alive: PropTypes.bool,
matter: PropTypes.object,
socket: PropTypes.object,
productIDs: PropTypes.array,
Expand All @@ -861,6 +881,7 @@ Bridges.propTypes = {
bridgeStates: PropTypes.object,
showToast: PropTypes.func,
commissioning: PropTypes.object,
checkLicenseOnAdd: PropTypes.func,
};

export default withStyles(styles)(Bridges);
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ import PropTypes from 'prop-types';
import { withStyles } from '@mui/styles';

import {
FormControl,
InputLabel,
MenuItem,
Select,
Switch, TextField,
Switch,
} from '@mui/material';

import { I18n } from '@iobroker/adapter-react-v5';
Expand All @@ -31,10 +27,6 @@ const styles = () => ({
});

class Controller extends React.Component {
constructor(props) {
super(props);
}

render() {
return <div className={this.props.classes.panel}>
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ class Devices extends React.Component {
}

Devices.propTypes = {
alive: PropTypes.bool,
matter: PropTypes.object,
socket: PropTypes.object,
productIDs: PropTypes.array,
Expand All @@ -398,6 +399,7 @@ Devices.propTypes = {
detectedDevices: PropTypes.array,
setDetectedDevices: PropTypes.func,
commissioning: PropTypes.object,
checkLicenseOnAdd: PropTypes.func,
};

export default withStyles(styles)(Devices);
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
TextField,
} from '@mui/material';

import {I18n, Logo} from '@iobroker/adapter-react-v5';
import { I18n, Logo } from '@iobroker/adapter-react-v5';
import { Check, Close, LayersClear } from '@mui/icons-material';

const styles = () => ({
Expand All @@ -39,7 +39,10 @@ class Options extends React.Component {
super(props);
this.state = {
showDialog: false,
dialogLevel: 0
dialogLevel: 0,
iotLogin: '',
iotPassword: '',
iotInstance: '',
};
}

Expand All @@ -59,27 +62,27 @@ class Options extends React.Component {
<br />
{I18n.t('The configuration of controller, bridges and devices will stay unchanged.')}
<br />
{this.state.level ? I18n.t('Are you really sure?') :I18n.t('Are you sure?')}
{this.state.dialogLevel ? I18n.t('Are you really sure?') : I18n.t('Are you sure?')}
</DialogContent>
<DialogActions>
<Button
variant="contained"
style={{ backgroundColor: this.state.level === 1 ? 'red' : undefined, color: this.state.level === 1 ? 'white' : undefined }}
style={{ backgroundColor: this.state.dialogLevel === 1 ? 'red' : undefined, color: this.state.dialogLevel === 1 ? 'white' : undefined }}
color="grey"
onClick={() => {
if (this.state.level === 1) {
if (this.state.dialogLevel === 1) {
this.setState({ showDialog: false });
// send command to reset all states
this.props.socket.sendTo(`matter.${this.props.instance}`, 'reset', { })
.then(() => this.props.showToast(I18n.t('Done')))
.catch(e => this.props.showToast(`Cannot reset: ${e}`));
} else {
this.setState({ level: 1 });
this.setState({ dialogLevel: 1 });
}
}}
startIcon={<Check />}
>
{this.state.level === 1 ? I18n.t('Reset it at least to defaults') : I18n.t('Reset to defaults')}
{this.state.dialogLevel === 1 ? I18n.t('Reset it at least to defaults') : I18n.t('Reset to defaults')}
</Button>
<Button
variant="contained"
Expand All @@ -91,10 +94,33 @@ class Options extends React.Component {
{I18n.t('Cancel')}
</Button>
</DialogActions>
</Dialog>
</Dialog>;
}

async componentDidMount() {
// detect if any iot or cloud with pro-account are available
const instancesIot = await this.props.socket.getAdapterInstances('iot');
let instance;
if (instancesIot) {
instance = instancesIot.find(it => it?.native?.login && it?.native?.pass);
if (instance) {
// encode
const pass = await this.props.socket.decrypt(instance.native.pass);

this.setState({ iotInstance: instance._id, iotPassword: pass, iotLogin: instance.native.login });
}
}
if (!instance) {
const instancesCloud = await this.props.socket.getAdapterInstances('cloud');
instance = instancesCloud.find(it => it?.native?.login && it?.native?.pass);
if (instance) {
// encode
const pass = await this.props.socket.decrypt(instance.native.pass);

this.setState({ iotInstance: instance._id, iotPassword: pass, iotLogin: instance.native.login });
}
}

try {
const host = await this.props.socket.getObject(`system.host.${this.props.common.host}`);
const interfaces = [
Expand Down Expand Up @@ -177,7 +203,7 @@ class Options extends React.Component {
</FormControl>}

<div style={{ marginTop: 50 }}>{I18n.t('Only required if you want to use bridge or device options with more than 5 devices')}</div>
<div style={{ display: 'flex' }}>
<div style={{ display: 'flex', alignItems: 'baseline' }}>
<TextField
variant="standard"
label={I18n.t('ioBroker.pro Login')}
Expand All @@ -194,17 +220,29 @@ class Options extends React.Component {
error={!!passwordError}
autoComplete="current-password"
className={this.props.classes.input}
value={this.props.native.password}
value={this.props.native.pass}
type="password"
helperText={passwordError || ''}
onChange={e => this.props.onChange('password', e.target.value)}
onChange={e => this.props.onChange('pass', e.target.value)}
margin="normal"
/>
{this.state.iotInstance && this.state.iotPassword !== this.props.native.pass && this.state.iotLogin !== this.props.native.login ?
<Button
style={{ marginLeft: 16 }}
variant="contained"
color="primary"
onClick={() => {
this.props.onChange('login', this.state.iotLogin);
this.props.onChange('pass', this.state.iotPassword);
}}
>
{I18n.t('Sync credentials with %s', this.state.iotInstance)}
</Button> : null}
</div>
<div style={{ marginTop: 50 }}>
<Button
disabled={!this.props.alive}
onClick={() => this.setState({ showDialog: true, level: 0 })}
onClick={() => this.setState({ showDialog: true, dialogLevel: 0 })}
variant="contained"
color="grey"
startIcon={<LayersClear />}
Expand Down
3 changes: 1 addition & 2 deletions src-admin/src/components/ConfigHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class ConfigHandler {
}
changed && this.onCommissioningChanged(this.commissioning);
}
}
};

onObjectChange = (id, obj) => {
if (id.startsWith(`matter.${this.instance}.devices.`)) {
Expand Down Expand Up @@ -241,7 +241,6 @@ class ConfigHandler {
this.commissioning.devices[parts[3]] = commissioning[id].val;
}
});

} catch (e) {
// ignore
}
Expand Down
Loading

0 comments on commit 41d7100

Please sign in to comment.