The Object Network

Object Network Types

The Object Network Types are a set of formats for common object types and their interactions and behaviours.

Commoditising types

Since the set of types is open-ended, any implementation needs a plugin or dynamic code-loading mechanism to enable it to generate, render and enable interaction with new types.

This will have the effect of commoditising common types that may currently be locked in to proprietary applications and services, such as chat or messaging, photo sharing, and so on.

You can re-use a map or calendar for anything you're doing, instead of having a separate map and calendar for every isolated application. Similarly, you only have one AR or VR view, which can handle multiple, even quite independent AR layers, or several unbounded, connected virtual worlds. You only have one user identity instead of one for every separate application.

The types include one for laying out 2D user interface panels in 3D space and getting input from the user. Hence, while waiting for a new candidate common type to settle and need a plugin, there will always be the option of an Object Network ruleset to convert that type to and from this user interface or 'gui' type. Similarly, there are basic 3D scenegraph and mesh types, allowing higher level but still common object types (like 'leaf') to initially be defined via a rule mapping.

Fields

The main property is "is" - which is a list of labels giving the object a type. There may be many types "mixed in" to an object, raising expectations of (a) the presence of certain properties (b) the presence of certain behaviours, and/or (c) the ability to react to, or interest in observing, certain peer types.

Most fields will be defined within the type or format that an object "is", but many will stand alone. For example, "title" is something that will mean the same in any format, as will "location", and other common fields, such as "created" and "author".

The semantics, if not the exact syntax, of certain fields will usually be declared in the Object Network as being defined in some other standard (e.g. events by iCalendar). Almost by definition we don't have namespacing in the Object Net Types. The whole point is to encourage discussion and agreement, not isolation.


The remainder of this page shows a number of examples, applications and patterns using the Object Network Type formats in ONF format, and using the ONR Language.

Event

An Event type carries a time period and optional location for an event. It can be used for calendar events, and can be mapped onto iCalendar:

{ UID: http://object.network/events/uid-f330a3-4011e.cyr
  is: attendable event
  title: "The Object Network Conference"
  content: "This year is expected to be the best yet!"
  start: "30 Sep 2016 09:00:00 GMT"
  end:   " 1 Oct 2016 23:00:00 GMT"
  location: http://bletchleypark.org/address.cyr
  attendees: uid-0fe6-7d5d
}

An Event type may normally be just "event", but here it's an "attendable event", because it's expecting RSVPs. The attendable type is a "mixin" that indicates the type of object this object is interested in.

The "start" and "end" properties map onto iCalendar's "DTSTART" and "DTEND".

The "location" is the UID of a contact type (is: contact). The "attendees" property is a list of links to the contact objects of the attendees.

RSVP

Since this Event is attendable, you know you can reply, to be hopefully added to the list of attendees, with an RSVP type:

{ UID: http://fred.info/o/uid-8a95-22bc0f7.cyr
  Notify: http://object.network/events/uid-f330a3-4011e.cyr
  is: rsvp
  event: http://object.network/events/uid-f330a3-4011e.cyr
  person: http://..
  attending: yes
}

This RSVP is hosted on fred.info, not object.network like the event itself. It is a persistent, updatable state, that is Notifying itself to the event.

Language Rule

When this RSVP is received at the event, there can be a Rule type to handle it that may look like this:

{ UID: http://object.network/rules/uid-34-234-23-23.cyr
  is: attendable event rule
  when: "RSVP attending received ensure user is in attendees"
  Alerted: { is: rsvp  event: @  attending: yes }
  attendees: => @. with @Alerted
}

The Alerted property is the other end of Notify - it's a link to the RSVP, and in the rule, you can jump right into the content to match its properties. Its event property is @, which means a link to the current object. The attendees property becomes (=>) itself (@.) but with the Alerted link if it's not already there

Here's the rule for removing someone who is no longer attending:

{ UID: http://object.network/rules/uid-fa82-a11-003.cyr
  is: attendable event rule
  when: "RSVP not attending ensure user not in attendees"
  attendees: { attending: no } => #
}

The link to an RSVP that is no longer attending becomes nothing (#).

The rules are attached to the event they animate by links:

{ UID: http://object.network/events/uid-f330a3-4011e.cyr
  is: attendable event
  Rules: uid-34-234-23-23 uid-fa82-a11-003
  title: "The Object Network Conference"
  :
}

Nested Event

An Event can have sub-events - for example, a conference has many talks. These are represented by the sub-objects/within pattern that is available for all types:

{ UID: uid-0112-09a9-3f54-b720
  is: attendable event
  title: "Geek Speak December"
  text: "Europe's Top Tech"
  start: "Wed 12 Dec 2012 18:00:00 GMT"
  end:   "Wed 12 Dec 2012 23:00:00 GMT"
  sub-objects: uid-3e0e-a630-b669-23d7 uid-0a01-cec7-61b7-a770
}

{ UID: uid-3e0e-a630-b669-23d7
  is: event
  title: "My Love of Clojure"
  text: "Long ago, I fell in love with Lisp.."
  start: "Wed 12 Dec 2012 18:00:00 GMT"
  end:   "Wed 12 Dec 2012 19:00:00 GMT"
  within: uid-0112-09a9-3f54-b720
}

Reviewable Event

An Event can be ratable and reviewable by adding is: rateable and a gui view:

{ UID: uid-3e0e-a630-b669-23d7
  is: rateable gui event
  title: "My Love of Clojure"
  text: "Long ago, I fell in love with Lisp.."
  start: "Wed 12 Dec 2012 18:00:00 GMT"
  end:   "Wed 12 Dec 2012 19:00:00 GMT"
  within: uid-0112-09a9-3f54-b720
  view: {
    email:      { input: textfield label: "Your Email:" }
    comments:   { input: textfield label: "Comments:" }
    pres-style: { input: rating    label: "Presentation Style:" }
  }
}

This expects an RSVP/form type back:

{ UID: uid-3e0e-a630-b669-23d7
  is: rsvp form
  event: uid-3e0e-a630-b669-23d7
  within: http://..
  rating: 5
  form:{
    email: foo@bar.com
    comments: "A good show.."
    pres-style: 4
  }
}

Contact

The Contact type is based on vCard:

A minimal contact:

{ is: contact
  name: {
    given:  Duncan
    middle: Beaumont
    family: Cragg
  }
  address: {
      locality: "Kingston-upon-Thames"
      region: Surrey
      postal-code: "KT1"
      country: UK
  }
  email: demo@cilux.org
}

A maximal contact:

{ is: contact
  name: {
    given:  Duncan
    middle: Beaumont
    family: Cragg
  }
  full-name: "Mr Duncan Cragg"
  address: {
      locality: "Kingston-upon-Thames"
      region: Surrey
      postal-code: "KT1"
      country: UK
  }
  email: demo@cilux.org
  organisation: {
      full-name: "ThoughtWorks (UK) Ltd"
      web-view: http://www.thoughtworks.com
      More: http://forest-roa.org/567-890.json
  }
  birthday: 1964-01-01
  web-view:
      http://duncan-cragg.org/blog/
      http://twitter.com/duncancragg
  publications:
      http://rd.springer.com/export-citation/chapter/10.1007/978-1-4419-8303-9_7.json
      http://object.network/111-111.json
      http://duncan-cragg.org/blog/atom.cyr
      http://duncan-cragg.org/blog/
  bio: "Creator of the [Object Network][http://object.network] and Object-Mash"
  attending:
       http://object.network/123-456.json
       http://api2.object.network/lanyrd/2013/overtheair.json
  employer:
       http://forest-roa.org/567-890.json
  inspirations:
        http://api2.object.network/dbpedia/Tim_Berners-Lee.json
        http://api2.object.network/dbpedia/Alan_Turing.json
  More: http://api2.object.network/twitter/duncancragg.json
}

Land

The Land type describes a physical area on a map:

{ UID: ...
  is: land
  title: "My Holding"
  area: 321.123
  shape: { lat: 54.106037, lon: -1.579163 }
         { lat: 54.106039, lon: -1.579231 }
         { lat: 54.106039, lon: -1.579232 }
         { lat: 54.106036, lon: -1.579162 }
}


Article

The Article type is used for blog entries, etc. It's partly based on Atom:

{ UID: http://duncan-cragg.org/blog/post/building-object-network/atom.cyr
  is: article
  title: "Building The Object Network"
  published: 2014-01-27T11:36:00Z
  updated: 2014-01-27T11:36:00Z
  web-view: http://duncan-cragg.org/blog/post/building-object-network/
  within: http://duncan-cragg.org/blog/atom.cyr
  tags: architecture declarative forest netmash cyrus object-network IoT
  text:
    "I've started another blog called [Building The Object Network][http://object-network.blogspot.co.uk/], about how I'm experimenting with Augmented Reality for the Internet of Things using the Object Network approach.",
    "So far I've been [blogging][http://object-network.blogspot.co.uk/2014/01/the-internet-of-3d-sensors-and-actuators.html] [every][http://object-network.blogspot.co.uk/2014/01/augmented-reality-and-magic.html] [day][http://object-network.blogspot.co.uk/2014/01/android-sensors-for-ar.html]."
    "Do subscribe! "
}

Article List

The Article List type is basically a feed, again based partly on Atom:

{ UID: http://duncan-cragg.org/blog/atom.cyr
  is: queryable article list
  title: "What Not How"
  sub-title: "Duncan Cragg on Declarative Architectures"
  author: http://duncan-cragg.org/blog/777-777.json
  id: http://duncan-cragg.org/blog/
  logo: http://duncan-cragg.org/favicon.gif
  icon: http://duncan-cragg.org/favicon.ico
  rights: "All content including photos and images by Duncan Cragg. Copyright (c) Duncan Cragg."
  generator: "Duncan Cragg's Django Blog"
  web-view: http://duncan-cragg.org/blog/
  atom: http://duncan-cragg.org/blog/atom/
  updated: 2014-01-27T11:36:00Z
  list: {
    is: article
    title: "Building The Object Network"
    published: 2014-01-27T11:36:00Z
    web-view: http://duncan-cragg.org/blog/post/building-object-network/
    More: http://duncan-cragg.org/blog/post/building-object-network/atom.cyr
  }{
    is: article
    title: "Cyrus in 2013"
    published: 2013-01-16T17:09:00Z
    web-view: http://duncan-cragg.org/blog/post/cyrus-2013/
    More: http://duncan-cragg.org/blog/post/cyrus-2013/atom.cyr
  }
}

It has a queryable "mixin", indicating that you can send a query..

Query

The Query Type can be notified to a queryable list, in this case, the above article list:

{ UID: http://
  is: article query
  querying: http://duncan-cragg.org/blog/atom.cyr
  match: {
    published: >= 2013-01-16T17:09:00Z
  }
}

It returns another, smaller article list than the one being queried, with a link to this query ("query").

Here is simple a rule that can run this query and return the response:

{ UID: http://
  is: article list rule
  Alerted: { is: article query  target: @ }
  list: maybe @Alerted:match
  latest-response: => {
    UID: new
    Notify: @Alerted
    is: article list
    title: "Query results"
    source: @
    query: @Alerted
    list: @=list
  }
}

There are many query parameters that can be added. Here's a query that uses most of them:

{ UID: http://
  is: article query
  querying: http://duncan-cragg.org/blog/atom.cyr
  match: {
    tags: architecture cyrus
  }
  page-size: 4
  page-start: 2
  order-by: { published: > }
  inline: true
  results: tracking
}

Setting inline: true brings the results inline to the list, along with More: links to the individual result entries. The results: tracking parameter means that this response will be kept up-to-date as the matching results set changes.

This could return:

{ UID: http://duncan-cragg.org/..
  is: article list
  list: {
    is: article
    title: "Building The Object Network"
    published: 2014-01-27T11:36:00Z
    updated: 2014-01-27T11:36:00Z
    web-view: http://duncan-cragg.org/blog/post/building-object-network/
    within: http://duncan-cragg.org/blog/atom.cyr
    tags: architecture declarative forest netmash cyrus object-network IoT
    text:
      "I've started another blog called [Building The Object Network][http://object-network.blogspot.co.uk/], about how I'm experimenting with Augmented Reality for the Internet of Things using the Object Network approach.",
      "So far I've been [blogging][http://object-network.blogspot.co.uk/2014/01/the-internet-of-3d-sensors-and-actuators.html] [every][http://object-network.blogspot.co.uk/2014/01/augmented-reality-and-magic.html] [day][http://object-network.blogspot.co.uk/2014/01/android-sensors-for-ar.html]."
      "Do subscribe! "
    More: http://duncan-cragg.org/blog/post/building-object-network/atom.cyr
  }{
    is: article
    title: "Cyrus in 2013"
    published: 2013-01-16T17:09:00Z
    web-view: http://duncan-cragg.org/blog/post/cyrus-2013/
    :
    More: http://duncan-cragg.org/blog/post/cyrus-2013/atom.cyr
  }
}

GUI

The GUI type is a 2D layout with form elements can be defined as follows:

{ UID: ..
  is: gui
  title: "Page Title"
  view: { logo: http://..
          text: ".."
          xxx: { input: button label: "Push me" }
          yyy: { input: chooser label: "xxx:"
                 range: {
                   a: "A a"
                   b: "B b"
                   c: "C c"
                 }
          }
          zzz: { input: textfield label: ".." }
          mmm: { input: checkbox  label: ".." }
          mmm: { input: rating    label: ".." }
  }
}

Form

The Form type is sent back to the GUI object - when a client sees and renders a GUI with form elements then if there are input elements it can allow the user to create a form object:

{ UID: http://
  is: form
  gui: http://...
  user: http://...
  form: {
    pushed: xxx
    yyy: b
  }
}

Calculator example

Here is a simple calculator using the gui/form types:

{ UID: uid-7356-dfcc-2173-4525
  is: editable gui
  title: Calculator
  local: { acc: 0 num: 0 op: + }
  Rules:
    { is: gui rule  Alerted: { is: form }  local: { key: => @Alerted:form:pushed } }
    { is: gui rule  local: { key: /[0-9]/  num: => join (@. @local:key) } }
    { is: gui rule  local: { key: dp       num: => if (not @. contains .) then (join (@. .)) else @. } }
    { is: gui rule  local: { key: cl       num: => 0 }}
    { is: gui rule
      local: {
        key: /pl|mi|ti|di|eq/
        acc: => if (@local:num set) then (@. @local:op @local:num) else @.
        op: => { pl: +  mi: -  ti: ×  di: ÷  eq: + } select @local:key
        num: => #
      }
    }
    { is: gui rule  local: { key: cs  num: #  acc: => @. × -1  } }
    { is: gui rule  local: { key: cs  num: * => @. × -1 } }
    { is: gui rule  local: { key: ms  mem: => if (@local:num set) then @local:num else @local:acc } }
    { is: gui rule  local: { key: mr  num: => if (@local:mem set) then @local:mem else @. } }
    { is: gui rule  local: { key: * => # } view: { result: { value: => if (@local:num set) then @local:num else @local:acc }}}
  view: {
   result: { is: style direction: horizontal } { input: textfield  value: 0 }
   buttons:
     { style: { is: style direction: horizontal } 7: { input: button label: 7 }  8: { input: button label: 8 }  9: { input: button label: 9 } ti: { input: button label: × } cs: { input: button label: +/- } }
     { style: { is: style direction: horizontal } 4: { input: button label: 4 }  5: { input: button label: 5 }  6: { input: button label: 6 } di: { input: button label: ÷ } ms: { input: button label: MS  } }
     { style: { is: style direction: horizontal } 1: { input: button label: 1 }  2: { input: button label: 2 }  3: { input: button label: 3 } pl: { input: button label: + } mr: { input: button label: MR  } }
     { style: { is: style direction: horizontal } 0: { input: button label: 0 } dp: { input: button label: . } cl: { input: button label: C } mi: { input: button label: - } eq: { input: button label: =   } }
  }
}

Supplier

The Supplier type lists offerings (products, services, etc.) and links to outstanding order or application trackers of those offerings:

{ UID: http://coffee-shop.com/baristas
  is: coffee shop supplier
  products:
    { title: "Espresso"   More: /prod/esp1 }
    { title: "Cappuccino" More: /prod/cap2 }
  trackers:
    http://coffee-shop.com/track111
    http://coffee-shop.com/track110
    http://coffee-shop.com/track109
}

The trackers list may be kept in a separate list object. Lists of services are tagged services instead of products.

Product/Service

The Product type is linked to by a supplier and describes the products on offer:

{ UID: http://coffee-shop.com/prod/esp1
  is: coffee product gui
  supplier: http://coffee-shop.com/baristas
  title: "Espresso"
  description: "A shot of pure coffee"
  view: {
    shots:     { input: textfield label: "Shots" range: 1 .. 5 }
    ristretto: { input: checkbox  label: "Ristretto" }
  }
  price-text: "£1.50 single £2.50 double"
}

Being also a GUI type means it has a customisation gui allowing various fields to be added to the order.

There is also an equivalent service type, which is basically the same.

Order/Application

The Order type lists products requested from a supplier:

{ UID: http://my-orders.com/ordr321
  is: coffee order
  products: { product: http:/coffee-shop.com/prod/esp1  quantity: 1  shots: 2  ristretto: false }
            { product: http:/coffee-shop.com/prod/cap2  quantity: 3  shots: 1 }
  supplier: http://coffee-shop.com/baristas
  tracker: http://coffee-shop.com/track111
  payment: http://my-orders.com/paym432
}

An order can have a list of product line items with link to product and quantity. The GUI form values are sent alongside the product link to which they refer.

There is also an equivalent application type, which is basically the same, but is used for requests for services or products where there is an assessment or eligibility aspect to supply of that service. It may have a services link instead of products, and has assessment instead of tracker.

An order may have invoice and delivery addresses as well as a general contact, which are links to contact objects:

{ UID: http://my-orders.com/ordr5422
  is: book order
  products: { product: /prod/book498239872  quantity: 1 }
  supplier: http://book-shop.com/
  tracker: http://book-shop.com/track1a40
  contact: http://my-orders.com/addr4332424
  invoice: http://my-orders.com/addr4332424
  delivery: http://my-orders.com/addr4332424
}

OrderTracker/Assessment

The OrderTracker type is owned by the supplier and tracks fulfilment of an order:

{ UID: http://coffee-shop.com/track111
  is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1  quantity: 1  shots: 1  ristretto: false }
  price: "£1.50"
  status: waiting { coffee: running  milk: frothing } priority-order
}

The status property may be complex: it may be a list of strings and/or sub-objects.

There is also an equivalent assessment type, which is used to evaluate and track applications rather than orders. It has a link to application instead of order, and may have a services link instead of products:

{ UID: http://barista-training.com/assess123123
  is: barista assessment
  application: http://barista-joe.com/application-to-pret
  contact: http://barista-joe.com/contact-card
  documents: http://visas.gov.uk/right-to-work/a7b3300.json http://barista-joe.com/CV.html
  services: { service: /barista-training/course32132  grade: master }
  price: "£150"
  status: { ristretto-quality: pass  frothy-ferns: 3.5  cleaning-up: under-evaluation }
}

Here, the contact link has been copied over from the application, but it can be found indirectly through the cached application link. There is also a link for supporting documentation that may be needed for an assessement.

Coffee Shop Example

There is a tradition in the distributed systems or integration community to use the example of ordering coffee to demonstrate your asynchronous system integration or distribution model.

It started with Gregor Hohpe's article about asynchronous messaging, then was continued by Jim Webber as "RESTbucks" to discuss his REST interpretation in an open forum and subsequently used to describe a refined version of the approach in the book by Jim and Ian Robinson.

Here's the Object Network version. It's based on the Foreign Exchange ordering example I used in my FOREST paper, which in turn was actually a coffee ordering scenario in its first drafts.

-------------------------------------------------
{ UID: http://coffee-shop.com/baristas
  is: coffee shop supplier
  products:
    { title: "Espresso"   More: /prod/esp1 }
    { title: "Cappuccino" More: /prod/cap2 }
  trackers:
    http://coffee-shop.com/track110
    http://coffee-shop.com/track109
}
-------------------------------------------------
{ UID: http://coffee-shop.com/prod/esp1
  is: coffee product gui
  supplier: http://coffee-shop.com/baristas
  title: "Espresso"
  description: "A shot of pure coffee"
  view: {
    shots:     { input: textfield label: "Shots" range: 1 .. 5 }
    ristretto: { input: checkbox  label: "Ristretto" }
  }
  price-text: "£1.50 single £2.50 double"
}
-------------------------------------------------
{ UID: http://my-orders.com/ordr321
  Notify: http://coffee-shop.com/baristas
  is: coffee order
  products: { product: http://coffee-shop.com/prod/esp1 quantity: 1 shots: 1 ristretto: false }
  supplier: http://coffee-shop.com/baristas
}

{ is: coffee shop supplier rule
  Alerted: { is: coffee order  supplier: @ }
  trackers: not { order: @Alerted } => @. with
    { UID: new
      Notify: @Alerted
      is: coffee order-tracker
      order: @Alerted
      products: @Alerted:products
      price: ..
      status: waiting
    }
}
-------------------------------------------------
{ is: coffee shop supplier
  products:
    { title: "Espresso"   More: /prod/esp1 }
    { title: "Cappuccino" More: /prod/cap2 }
  trackers:
    http://coffee-shop.com/track111
    http://coffee-shop.com/track110
    http://coffee-shop.com/track109
}

{ UID: http://coffee-shop.com/track111
  Notify: http://my-orders.com/ordr321
  is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1 quantity: 1 shots: 1 ristretto: false }
  price: "£1.50"
  status: waiting
}
-------------------------------------------------
{ UID: http://my-orders.com/ordr321
  Notify: http://coffee-shop.com/track111
  is: coffee order
  products: { product: http://coffee-shop.com/prod/esp1 quantity: 1 shots: 2 ristretto: false }
  supplier: http://coffee-shop.com/baristas
  tracker: http://coffee-shop.com/track111
}

{ is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1 quantity: 1 shots: 2 ristretto: false }
  price: "£2.50"
  status: waiting
}
-------------------------------------------------
{ is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1 quantity: 1 shots: 2 ristretto: false }
  price: "£2.50"
  status: filled
}
-------------------------------------------------
{ is: coffee order
  products: { product: http://coffee-shop.com/prod/cap2 quantity: 1 shots: 2 }
  supplier: http://coffee-shop.com/baristas
  tracker: http://coffee-shop.com/track111
}

{ is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1 quantity: 1 shots: 2 ristretto: false }
  price: "£2.50"
  status: filled not-as-ordered
}
-------------------------------------------------
{ is: coffee order
  products: cancelled
  supplier: http://coffee-shop.com/baristas
  tracker: http://coffee-shop.com/track111
}

{ is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1 quantity: 1 shots: 2 ristretto: false }
  price: "£0.00"
  status: cancelled
}
-------------------------------------------------
{ is: coffee order
  products: { product: http://coffee-shop.com/prod/esp1 quantity: 1 shots: 2 ristretto: false }
  supplier: http://coffee-shop.com/baristas
  tracker: http://coffee-shop.com/track111
}

{ is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1 quantity: 1 shots: 2 ristretto: false }
  price: "£2.50"
  status: filled
}
-------------------------------------------------
{ is: coffee order
  products: { product: http://coffee-shop.com/prod/esp1 quantity: 1 shots: 2 ristretto: false }
  supplier: http://coffee-shop.com/baristas
  tracker: http://coffee-shop.com/track111
  payment: http://my-orders.com/paym432
}
-------------------------------------------------
{ UID: http://my-orders.com/paym432
  is: payment
  invoice: http://coffee-shop.com/track111
  order: http://my-orders.com/ordr321
  amount: £2.50
  account: { .. }
}
-------------------------------------------------
{ is: coffee order-tracker
  order: http://my-orders.com/ordr321
  products: { product: /prod/esp1 quantity: 1 shots: 2 ristretto: false }
  price: "£2.50"
  status: paid
  payment: http://my-orders.com/paym432
}
-------------------------------------------------

3D Objects

3D Object type :

{ UID: http://../uid-7794-3aa8-2192-7a60
  is: 3d mesh
  title: Avatar
  rotation: 0 45 0
  scale: 1 1 1
  vertices:
    (  1  0  0 ) (  1  0  1 ) (  0  0  1 ) (  0  0  0 )
    (  1  1  0 ) (  1  1  1 ) (  0  1  1 ) (  0  1  0 )
  texturepoints: ( 0.0 0.0 ) ( 1.0 0.0 ) ( 1.0 1.0 ) ( 0.0 1.0 )
  normals: ( -1.0  0.0  0.0 ) ( 1.0 0.0 0.0 )
           (  0.0 -1.0  0.0 ) ( 0.0 1.0 0.0 )
           (  0.0  0.0 -1.0 ) ( 0.0 0.0 1.0 )
  faces:
    ( 5/1/5 1/2/5 4/3/5 ) ( 5/1/5 4/3/5 8/4/5 ) ( 3/1/1 7/2/1 8/3/1 )
    ( 3/1/1 8/3/1 4/4/1 ) ( 2/1/6 6/2/6 3/4/6 ) ( 6/2/6 7/3/6 3/4/6 )
    ( 1/1/2 5/2/2 2/4/2 ) ( 5/2/2 6/3/2 2/4/2 ) ( 5/1/4 8/2/4 6/4/4 )
    ( 8/2/4 7/3/4 6/4/4 ) ( 1/1/3 2/2/3 3/3/3 ) ( 1/1/3 3/3/3 4/4/3 )
  textures: http://fc08.deviantart.net/fs51/i/2009/284/5/e/IMVU_eye_texture_by_lilylisete.png
  vertex-shader: http://10.0.2.2:8081/o/uid-ff5d-1ef4-cfa5-5f92.json
  fragment-shader: http://10.0.2.2:8081/o/uid-1ff8-59e9-6dac-9b56.json
}

Here is how shaders are published:

{ is: 3d vertex shader string list
  title: "Dynamic Phong Vertex Shader"
  list:
    "uniform mat4 mvpm, mvvm;"
    "attribute vec4 pos;"
    "attribute vec2 tex;"
    "attribute vec3 nor;"
    "varying vec3 mvvp;"
    "varying vec2 texturePt;"
    "varying vec3 mvvn;"
    "void main(){"
      "texturePt = tex;"
      "mvvp = vec3(mvvm*pos);"
      "mvvn = vec3(mvvm*vec4(nor,0.0));"
      "gl_Position = mvpm*pos;"
    "}"
}

User

The User Type represents the live, dynamic user that is active in a wearable device, etc:

{ UID: http://
  is: user
  saying: " .. "
  within: ..
  position: 0.0 0.0 0.0
  avatar: http://
  location: { lat: 54.106037, lon: -1.579163 }
  contact: http://
  homeusers: http://
  private: {
    viewing: http://
    editing: http://
    viewas: gui
    links: ..
    links-around:
    history:  ..
    contacts: ..
    responses: { }
    position: { }
    orientation: { }
  }
}

Users may have current status ("saying"), a virtual place they're "within", a position in that place, an avatar object, a GPS location, a contact object, etc. The "homeusers" link is to a serverside "home" to which the user's state can be pushed, since users will typically be run asymmetrically, without the ability to be directly published.

The "private" section is all content that won't be pushed or published either because it's private data or because it's changing too fast and is too low-level for public use - it should be stripped off and kept only inside the device. It includes what the user is currently viewing, how they are viewing it (as a GUI, a map or raw data), their viewing history, contacts list, orientation of the device, etc.

Internet of Things example

This is the code from my 60 Days of Things project.

{ UID: uid-41b6-5f8f-f143-b30d
  Class: cyrus.types.PresenceTracker
  is: place 3d mesh editable
  title: "Room of Things"
  sub-items: { item: uid-52e0-e5c3-0ed1-6ed3 position: 15 1 10 }
  scale: 20 20 20
  vertices: ( 1 0 0 ) ( 1 0 1 ) ( 0 0 1 ) ( 0 0 0 )
  texturepoints: ( 0 0 ) ( 5 0 ) ( 5 5 ) ( 0 5 )
  normals: ( 0 1 0 )
  faces: ( 2/3/1 1/2/1 4/1/1 ) ( 2/3/1 4/1/1 3/4/1 )
  textures: http://www.textures123.com/free-texture/sand/sand-texture4.jpg
  vertex-shader: uid-ff5d-1ef4-cfa5-5f92
  fragment-shader: uid-1ff8-59e9-6dac-9b56
  x: 7
}

This is the room object where it all happens. It has a link to the following light sensor:

{ UID: uid-52e0-e5c3-0ed1-6ed3
  is: 3d cuboid editable light-sensor
  title: "Light Level"
  scale: 0.3 0.3 0.3
  within: uid-41b6-5f8f-f143-b30d
  textures: http://www.textures123.com/free-texture/sand/sand-texture4.jpg
  light-level: 100
}

There is a light on another server that links to the room/place object it is within:

{ Rules: http://netmash.net/o/uid-16bd-140a-8862-41cd.cyr
         http://netmash.net/o/uid-6f1a-4c7c-d111-2679.cyr
         http://netmash.net/o/uid-9011-94df-9feb-e3c2.cyr
         http://netmash.net/o/uid-2f18-945a-c460-9bd7.cyr
  is: 3d cuboid editable
  title: Light
  rotation: 45 45 45
  scale: 1 1 1
  light: 1 1 1
  position: 0 0 0
  within: http://10.0.2.2:8081/o/uid-41b6-5f8f-f143-b30d.json
}

It has four rules. First, how to set its colour on touch by the user:

{ UID: http://netmash.net/o/uid-16bd-140a-8862-41cd.cyr
  is: 3d rule
  when: "touched, set light colour"
  Alerted: { is: user  touching: { item: @ } }
  light: => @Alerted:touching:position * 1.4
}

Next, telling the room/place that it's here on start-up/discovery:

{ UID: http://netmash.net/o/uid-6f1a-4c7c-d111-2679.cyr
  is: 3d rule
  when: "starting, notify place within"
  Notify: => @. with @within
}

Getting a link to the light level sensor in the room, if any:

{ UID: http://netmash.net/o/uid-9011-94df-9feb-e3c2.cyr
  is: 3d rule
  when: "starting, get light-sensor"
  within: { sub-items: { item: { is: light-sensor } } }
  light-sensor: # => @=within:sub-items:item
}

And responding to the light level:


{ UID: http://netmash.net/o/uid-2f18-945a-c460-9bd7.cyr
  is: 3d rule
  when: "it gets dark, turn light on"
  light-sensor: { light-level: < 100 }
  light: => 1 1 1
}

This is a sketch of how to set a light brightness according to a dimmer object:

{ UID: uid-1
  Rules: uid-3
  is: light
  colour: 1 1 0
  light: 0.5.0.5 0
  dimmer: http://../uid-2
}

{ UID: uid-2
  is: dimmer
  setting: 0.5
}

{ UID: uid-3
  is: light rule
  light: => @colour × @dimmer:setting
}

Editable

The Editable type is a "mixin" type that means this object is happy to accept rules to update it:

{ UID: http://..
  Version: 33
  is: editable thing
  thing-prop: a
}

Here is what a typical edit rule may look like:

{ is: editable rule
  when: edited
  editable: http://..
  user: http://..
  : { Version: 33 } => as-is {
    is: editable thing
    thing-prop: b
  }
}

This rewrites the whole object (matching the single colon) matching version 33 to the given right-hand side. Of course, you could have a rule that rewrites just part of the target.

Duncan Cragg, 2016

Contact me and/or subscribe to my blog and/or follow me on Twitter.