Browse Source

More awesome work on stuff

update-deps
Alex Mikhalev 7 years ago
parent
commit
f9ae6fac6f
  1. 4
      app/components/DeviceView.tsx
  2. 4
      app/components/MessageTest.tsx
  3. 4
      app/components/MessagesView.tsx
  4. 5
      app/index.tsx
  5. 18
      app/state/index.ts
  6. 8
      app/state/inject.tsx
  7. 46
      app/state/web.ts
  8. 16
      common/sprinklers/SprinklersDevice.ts
  9. 21
      common/sprinklers/json/index.ts
  10. 8
      server/index.ts

4
app/components/DeviceView.tsx

@ -4,7 +4,7 @@ import * as React from "react"; @@ -4,7 +4,7 @@ import * as React from "react";
import FontAwesome = require("react-fontawesome");
import { Header, Item } from "semantic-ui-react";
import { injectState, State } from "@app/state";
import { injectState, MqttApiState } from "@app/state";
import { SprinklersDevice } from "@common/sprinklers";
import { ProgramTable, RunSectionForm, SectionRunnerView, SectionTable } from ".";
@ -24,7 +24,7 @@ const ConnectionState = ({ connected }: { connected: boolean }) => { @@ -24,7 +24,7 @@ const ConnectionState = ({ connected }: { connected: boolean }) => {
interface DeviceViewProps {
deviceId: string;
state: State;
state: MqttApiState;
}
class DeviceView extends React.Component<DeviceViewProps> {

4
app/components/MessageTest.tsx

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
import * as React from "react";
import { Button, Segment } from "semantic-ui-react";
import { injectState, State } from "@app/state";
import { injectState, MqttApiState } from "@app/state";
import { getRandomId } from "@common/utils";
class MessageTest extends React.Component<{ state: State }> {
class MessageTest extends React.Component<{ state: MqttApiState }> {
render() {
return (
<Segment>

4
app/components/MessagesView.tsx

@ -3,7 +3,7 @@ import { observer } from "mobx-react"; @@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import * as React from "react";
import { Message, MessageProps, TransitionGroup } from "semantic-ui-react";
import { injectState, State, UiMessage, UiStore } from "@app/state/";
import { injectState, MqttApiState, UiMessage, UiStore } from "@app/state/";
@observer
class MessageView extends React.Component<{
@ -33,7 +33,7 @@ class MessageView extends React.Component<{ @@ -33,7 +33,7 @@ class MessageView extends React.Component<{
}
}
class MessagesView extends React.Component<{ state: State }> {
class MessagesView extends React.Component<{ state: MqttApiState }> {
render() {
const { uiStore } = this.props.state;
const messages = uiStore.messages.map((message) => (

5
app/index.tsx

@ -3,12 +3,13 @@ import * as ReactDOM from "react-dom"; @@ -3,12 +3,13 @@ import * as ReactDOM from "react-dom";
import { AppContainer } from "react-hot-loader";
import App from "@app/components/App";
import { ProvideState, State } from "@app/state";
import { ProvideState, MqttApiState, WebApiState } from "@app/state";
import log, { setLogger } from "@common/logger";
setLogger(log.child({ name: "sprinklers3/app" }));
const state = new State();
// const state = new MqttApiState();
const state = new WebApiState();
state.start();
const rootElem = document.getElementById("app");

18
app/state/index.ts

@ -1,17 +1,13 @@ @@ -1,17 +1,13 @@
import { ISprinklersApi } from "@common/sprinklers";
import { MqttApiClient } from "@common/sprinklers/mqtt";
import { WebApiClient } from "./web";
import { UiMessage, UiStore } from "./ui";
export { UiMessage, UiStore };
export * from "./inject";
export interface IState {
sprinklersApi: ISprinklersApi;
uiStore: UiStore;
}
export class State implements IState {
sprinklersApi: ISprinklersApi = new MqttApiClient(`ws://${location.hostname}:1884`);
export abstract class StateBase {
abstract readonly sprinklersApi: ISprinklersApi;
uiStore = new UiStore();
constructor() {
@ -23,6 +19,14 @@ export class State implements IState { @@ -23,6 +19,14 @@ export class State implements IState {
}
}
export class MqttApiState extends StateBase {
sprinklersApi = new MqttApiClient(`ws://${location.hostname}:1884`);
}
export class WebApiState extends StateBase {
sprinklersApi = new WebApiClient();
}
// const state = new State();
// export default state;

8
app/state/inject.tsx

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
import * as PropTypes from "prop-types";
import * as React from "react";
import { State } from "@app/state";
import { StateBase } from "@app/state";
interface IProvidedStateContext {
providedState: State;
providedState: StateBase;
}
const providedStateContextTypes: PropTypes.ValidationMap<any> = {
@ -12,7 +12,7 @@ const providedStateContextTypes: PropTypes.ValidationMap<any> = { @@ -12,7 +12,7 @@ const providedStateContextTypes: PropTypes.ValidationMap<any> = {
};
export class ProvideState extends React.Component<{
state: State,
state: StateBase,
}> implements React.ChildContextProvider<IProvidedStateContext> {
static childContextTypes = providedStateContextTypes;
@ -30,7 +30,7 @@ export class ProvideState extends React.Component<{ @@ -30,7 +30,7 @@ export class ProvideState extends React.Component<{
type Diff<T extends string, U extends string> = ({[P in T]: P } & {[P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = {[P in Diff<keyof T, K>]: T[P]};
export function injectState<P extends { "state": State }>(Component: React.ComponentType<P>) {
export function injectState<P extends { "state": StateBase }>(Component: React.ComponentType<P>) {
return class extends React.Component<Omit<P, "state">> {
static contextTypes = providedStateContextTypes;
context: IProvidedStateContext;

46
app/state/web.ts

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
import { update } from "serializr";
import * as s from "@common/sprinklers";
import * as schema from "@common/sprinklers/json";
export class WebSprinklersDevice extends s.SprinklersDevice {
get id() {
return "grinklers";
}
async runSection(section: number | s.Section, duration: s.Duration): Promise<{}> {
return {};
}
async runProgram(program: number | s.Program): Promise<{}> {
return {};
}
async cancelSectionRunById(id: number): Promise<{}> {
return {};
}
async pauseSectionRunner(): Promise<{}> {
return {};
}
async unpauseSectionRunner(): Promise<{}> {
return {};
}
}
export class WebApiClient implements s.ISprinklersApi {
start() {
// NOT IMPLEMENTED
}
getDevice(name: string): s.SprinklersDevice {
const device = new WebSprinklersDevice();
fetch("/api/grinklers")
.then((res) => res.json())
.then((json) => {
update(schema.sprinklersDeviceSchema, device, json);
})
.catch((e) => alert(e));
return device;
}
removeDevice(name: string) {
// NOT IMPLEMENTED
}
}

16
common/sprinklers/SprinklersDevice.ts

@ -10,6 +10,10 @@ export abstract class SprinklersDevice { @@ -10,6 +10,10 @@ export abstract class SprinklersDevice {
@observable programs: Program[] = [];
@observable sectionRunner: SectionRunner;
constructor() {
this.sectionRunner = new (this.sectionRunnerConstructor)(this);
}
abstract get id(): string;
abstract runSection(section: number | Section, duration: Duration): Promise<{}>;
abstract runProgram(program: number | Program): Promise<{}>;
@ -17,9 +21,15 @@ export abstract class SprinklersDevice { @@ -17,9 +21,15 @@ export abstract class SprinklersDevice {
abstract pauseSectionRunner(): Promise<{}>;
abstract unpauseSectionRunner(): Promise<{}>;
abstract get sectionConstructor(): typeof Section;
abstract get sectionRunnerConstructor(): typeof SectionRunner;
abstract get programConstructor(): typeof Program;
get sectionConstructor(): typeof Section {
return Section;
}
get sectionRunnerConstructor(): typeof SectionRunner {
return SectionRunner;
}
get programConstructor(): typeof Program {
return Program;
}
toString(): string {
return `SprinklersDevice{id="${this.id}", connected=${this.connected}, ` +

21
common/sprinklers/json/index.ts

@ -8,15 +8,28 @@ import * as s from ".."; @@ -8,15 +8,28 @@ import * as s from "..";
export const durationSchema: PropSchema = {
serializer: (duration: s.Duration | null) =>
duration != null ? duration.toSeconds() : null,
deserializer: (json: any) =>
typeof json === "number" ? s.Duration.fromSeconds(json) : null,
deserializer: (json: any, done) => {
if (typeof json === "number") {
done(null, s.Duration.fromSeconds(json));
} else {
done(new Error(`Duration expects a number, not ${json}`), undefined);
}
},
};
export const dateSchema: PropSchema = {
serializer: (jsDate: Date | null) => jsDate != null ?
jsDate.toISOString() : null,
deserializer: (json: any) => typeof json === "string" ?
new Date(json) : null,
deserializer: (json: any, done) => {
if (json === null) {
done(null, null);
}
try {
done(null, new Date(json));
} catch (e) {
done(e, undefined);
}
},
};
export const dateOfYearSchema: ModelSchema<s.DateOfYear> = {

8
server/index.ts

@ -13,13 +13,17 @@ const mqttClient = new mqtt.MqttApiClient("mqtt://localhost:1883"); @@ -13,13 +13,17 @@ const mqttClient = new mqtt.MqttApiClient("mqtt://localhost:1883");
mqttClient.start();
import { sprinklersDeviceSchema } from "@common/sprinklers/json";
import { autorun } from "mobx";
import { autorunAsync } from "mobx";
import { serialize } from "serializr";
const device = mqttClient.getDevice("grinklers");
autorunAsync(() => {
const j = serialize(sprinklersDeviceSchema, device);
log.info({ device: j });
}, 0);
app.get("/api/grinklers", (req, res) => {
const j = serialize(sprinklersDeviceSchema, device);
log.trace(j);
res.send(j);
});

Loading…
Cancel
Save