Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association
In Socialtext Unplugged, the selected pages of your Socialtext workspace are displayed as individual "tiddlers" on the page. When the mouse passes over a tiddler a short toolbar menu appears at the top right. Use the commands here to manipulate that particular tiddler: notably closing and editting it. (You can double click on a tiddler as a shortcut to directly enter edit mode).
Over on the right hand side of the window are commands that affect the entire page, in particular "close all" which can be useful to clear the decks when many tiddlers are open at once.
The user is encouraged to ensure that they can SaveChanges before embarking on widespread editing.
Welcome to Socialtext Unplugged. This is a specially designed web page that you can use to view and edit your Socialtext content without having to be online to your Socialtext server.
There are three steps to using Socialtext Unplugged:
* First, learn how to SaveChanges to your local hard drive. This keeps your work safe even if you close your browser or have to reboot your computer
* Secondly, find out how to BrowseAndEdit your content while it is unplugged
* Thirdly, when you can reconnect to your Socialtext server, you can SyncChanges to save your unplugged changes to the server so that other people can see them too
You should also check your system meets the SystemRequirements.
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
<div class="socialtextLogo"><img src="http://www.eu.socialtext.net/static/2.3.0.0/images/st/logo/socialtext-logo-152x26.gif" width=152 height=26></div>
</div>
<!--}}}-->
Socialtext Unplugged lets you browse and edit your content while you're offline. When you make a change you need to SaveChanges to save the change to your local hard drive, before later performing a SyncChanges to synchronise the change back to the server.
The procedure for SaveChanges is slightly different for different browsers:
* SavingOnInternetExplorer
* SavingOnFireFox
* SavingOnSafari
* SavingOnOpera
You can save changes with any version of FireFox, and also many other browsers in the FireFox family, such as Camino on the Mac and MiniMo on mobile devices. The procedure is:
# Click the button labelled 'save changes' over in the right hand sidebar
# If prompted with an "Internet Security" dialog as follows, click the checkbox labelled "Remember this decision" and then the "Allow" button
## "A script from "file://" is requesting enhanced capabilities that are UNSAFE and could be used to compromise your machine or data..."
# You should then see a message at the top right of the window saying "Main TiddlyWiki file saved"
If you accidentally //deny// permission instead, you may need to UnravelFireFoxPermissions.
You can save changes with Internet Explorer versions 6 and 7, but not the earlier versions. The procedure is:
# Click the button labelled 'save changes' over in the right hand sidebar
# If prompted as follows, click "Yes":
## "An ActiveX control on this page might be unsafe to interact with other parts of the page. Do you want to allow this interaction?"
# You should then see a message at the top right of the window saying "Main TiddlyWiki file saved"
Note that there is currently [[a bug|http://trac.tiddlywiki.org/tiddlywiki/ticket/39]] that prevents Internet Explorer from saving correctly if you have specified a backup directory in AdvancedOptions.
To SaveChanges on Opera, see the instructions for using the TiddlySaver Java applet.
To SaveChanges on Safari, see the instructions for using the TiddlySaver Java applet.
<<search>><<closeAll>><<permaview>><<newTiddler 'New Tiddler' fields:'server.host:"https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443" server.workspace:"rot13" wikiformat:socialtext'>><<newJournal 'DD MMM YYYY' fields:'server.host:"https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443" server.workspace:"rot13" wikiformat:socialtext'>><<saveChanges>><<backstage sync>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
Dobrica Pavlinušić's random unstructured stuff
https://saturn.ffzg.hr/rot13/
[[SocialtextScreenStyle]]
[[SocialtextStyleOverrides]]
[[Styles HorizontalMainMenu]]
@@The user interface for synchronization is not finalized@@
To synchronize your changes back to the Socialtext server:
# click on [[Sync]] in the right-hand sidebar
<<tabs txtMoreTab Orphans 'Orphaned tiddlers' TabMoreOrphans Shadowed 'Shadowed tiddlers' TabMoreShadowed>>
Under FireFox, you can run into problems if you accidentally click 'Deny' on the permission request dialog, and have selected //Remember this decision//.
To reverse the effects, first locate the file {{{prefs.js}}} in your FireFox profile directory. Under Windows you'll find it at something like {{{C:\Documents and Settings\Jeremy\Application Data\Mozilla\Firefox\Profiles\o3dhupu6.default\prefs.js}}}, where {{{Jeremy}}} is the name of your windows profile and {{{o3dhupu6}}} will be a similar string of gobbledegook. On the Mac it'll be at {{{~/Library/Application Support/Firefox/Profiles/o3dhupu6.default/prefs.js}}} and on most versions of Linux, at {{{~/.mozilla/firefox/o3dhupu6.default/prefs.js}}}.
Open the file in a text editor and find the line {{{user_pref("capability.principal.codebase.p0.denied", "UniversalXPConnect");}}} and simply replace the word {{{denied}}} with {{{granted}}}.
//(Thanks to JonScully for figuring out this fix)//
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler references > fields syncing jump'></div>
<div class='workspace' id='st-page-wiki-title' macro='view socialtext.workspace'></div>
<div class='title' id='st-page-titletext' macro='view title'></div>
<div class='subtitle'>
Created on <span macro='view created date [[MMM DD, 0hh:0mm]]'></span>.
Updated by <span macro='view modifier link'></span>
on <span macro='view modified date [[MMM DD, 0hh:0mm]]'></span></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></span></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
To use, add {{{[[Styles HorizontalMainMenu]]}}} to your StyleSheet tiddler.
See http://www.w3schools.com/css/css_colors.asp for a color chart.
***/
/*{{{*/
#mainMenu {position:relative;left:auto;width:auto;text-align:left;line-height:normal;padding 0em 1em 0em 1em;font-size:normal;}
#mainMenu br {display:none;}
#mainMenu {background:#336699;}
#mainMenu {padding:2px;}
#mainMenu .button, #mainMenu .tiddlyLink {padding-left:0.5em;padding-right:0.5em;color:white;font-size:115%;}
#displayArea {
margin-top:0;margin-right:20em;margin-bottom:0;margin-left:1em;
padding-top:.1em;padding-bottom:.1em;
}
/*}}}*/
|''Type:''|socialtext|
|''URL:''|https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443 |
|''Workspace:''|rot13|
|''WorkspaceList:''||
|''Description:''|Dobrica Pavlinušić's random unstructured stuff|
The TiddlySaver Java applet allows TiddlyWiki from a {{{file://}}} URL to save changes Safari, Opera and other browsers.
It is a small file named [["TiddlySaver.jar"|TiddlySaver.jar]] that must be placed in the same directory as your TiddlyWiki file. Before you can use it, you need to give it the necessary privileges by editting your {{{.java.policy}}} file.
For Windows, the file will be at {{{C:\Documents and Settings\your-user-name\.java.policy}}}. Add the following lines (substituting the directory of your TiddlyWiki file as appropriate):
{{{
grant codeBase "file:${user.home}/My Documents/tiddlywiki-folder/*" {
permission java.io.FilePermission "${user.home}${/}My Documents${/}tiddlywiki-folder${/}*", "read,write";
};
}}}
On Mac OS X, the file is found at {{{/Users/your-user-name/.java.policy}}}:
{{{
grant codeBase "file:${user.home}/Documents/tiddlywiki-folder/*" {
permission java.io.FilePermission "${user.home}${/}Documents${/}tiddlywiki-folder${/}*", "read,write";
};
}}}
It can be tricky creating files whose name starts with a period, so you can use this [[pre-built .java.policy file|.java.policy]]. The same file is suitable for Macs too, just edit it and delete the "My " bit, leaving just "Documents". Make sure you save it in the right place for each operating system!
If you have trouble setting up the permissions correctly, you can try granting broader permissions to the applet like this:
{{{
grant codeBase "file://localhost/home/users/Desktop/
TiddlySaver.jar"
{ permission java.security.AllPermission; };
}}}
Note that there is currently [[a bug|http://trac.tiddlywiki.org/ticket/172]] that prevents TiddlySaver from working if you have specified a backup directory in AdvancedOptions.
/***
|''Name:''|SocialtextLocaleOverrides|
|''Description:''|Text changes for Socialtext|
***/
//{{{
merge(config.views.wikified.tag,{
labelNoTags: "No Tags",
labelTags: "Tags"});
merge(config.commands.references,{
text: "incoming links",
tooltip: "Show tiddlers that link to this one",
popupNone: "No incoming links"});
//}}}
/***
|''Name:''|SocialtextTweaksPlugin|
|''Description:''|Allows changes to be synchronised with a Socialtext server|
|''Source:''|http://stunplugged.tiddlywiki.com/#SocialtextTweaksPlugin|
|''Author:''|JeremyRuston (jeremy (at) osmosoft (dot) com)|
|''Version:''|1.0.2|
|''Date:''|Jun 15, 2006|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[BSD open source license]]|
|''~CoreVersion:''|2.2|
Make minor configuration tweaks specific to Socialtext Unplugged
***/
//{{{
// Ensure that the SocialtextTweaksPlugin is only installed once.
if(!version.extensions.SocialtextTweaksPlugin) {
version.extensions.SocialtextTweaksPlugin = {installed:true};
// Check version number of core code
if(version.major < 2 || (version.major == 2 && version.minor < 2))
{alertAndThrow("SocialtextTweaksPlugin requires TiddlyWiki 2.2 or later.");}
merge(config.defaultCustomFields,{
wikiformat:'socialtext',
'server.host':'https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443'
});
config.options.chkSinglePageMode = true;
config.options.chkEnableAnimations = true;
} // end of "install only once"
//}}}
/***
|''Name:''|SocialtextFormatterPlugin|
|''Description:''|Allows Tiddlers to use [[Socialtext|http://www.socialtext.com/]] text formatting|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com)|
|''Source:''|http://www.martinswiki.com/#SocialtextFormatterPlugin|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/formatters/SocialtextFormatterPlugin.js|
|''Version:''|0.9.4|
|''Date:''|Jan 21, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.1.0|
This is the SocialtextFormatterPlugin, which allows you to insert Socialtext formated text into a TiddlyWiki.
The aim is not to fully emulate Socialtext, but to allow you to work with Socialtext content off-line and then resync the content with your Socialtext wiki later on, with the expectation that only minor edits will be required.
To use Socialtext format in a Tiddler, tag the Tiddler with SocialtextFormat or set the tiddler's {{{wikiformat}}} extended field to {{{socialtext}}}
Please report any defects you find at http://groups.google.co.uk/group/TiddlyWikiDev
***/
//{{{
// Ensure that the SocialtextFormatter Plugin is only installed once.
if(!version.extensions.SocialtextFormatterPlugin) {
version.extensions.SocialtextFormatterPlugin = {installed:true};
if(version.major < 2 || (version.major == 2 && version.minor < 1))
{alertAndThrow('SocialtextFormatterPlugin requires TiddlyWiki 2.1 or later.');}
SocialtextFormatter = {}; // 'namespace' for local functions
wikify = function(source,output,highlightRegExp,tiddler)
{
if(source && source != '') {
var w = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
var out = output;
if(tiddler && (tiddler.isTagged(config.parsers.socialtextFormatter.formatTag) || (tiddler.fields.wikiformat==config.parsers.socialtextFormatter.format)) ) {
var d1 = createTiddlyElement(output,'div','content-display-body','content-section-visible');
var d2 = createTiddlyElement(d1,'div','wikipage');
out = createTiddlyElement(d2,'div',null,'wiki');
}
var time1,time0 = new Date();
w.subWikifyUnterm(out);
if(tiddler && config.options.chkDisplayInstrumentation) {
time1 = new Date();
var t = tiddler ? tiddler.title : source.substr(0,10);
displayMessage("Wikify '"+t+"' in " + (time1-time0) + " ms");
}
}
};
stDebug = function(out,str)
{
createTiddlyText(out,str.replace(/\n/mg,'\\n').replace(/\r/mg,'RR'));
createTiddlyElement(out,'br');
};
SocialtextFormatter.Tiddler_changed = Tiddler.prototype.changed;
Tiddler.prototype.changed = function()
{
if((this.fields.wikiformat==config.parsers.socialtextFormatter.format) || this.isTagged(config.parsers.socialtextFormatter.formatTag)) {
// update the links array, by checking for Socialtext format links
this.links = [];
var tiddlerLinkRegExp = /(?:\"(.*?)\" ?)?\[([^\]]*?)\]/mg;
tiddlerLinkRegExp.lastIndex = 0;
var match = tiddlerLinkRegExp.exec(this.text);
while(match) {
var link = match[2];
this.links.pushUnique(link);
match = tiddlerLinkRegExp.exec(this.text);
}
}/* else {
return SocialtextFormatter.Tiddler_changed.apply(this,arguments);
}*/
this.linksUpdated = true;
};
SocialtextFormatter.wafl = function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var lm2 = lookaheadMatch[2];
switch(lookaheadMatch[1]) {
case 'image':
var img = createTiddlyElement(w.output,'img');
img.src = w.tiddler.title + '/' + lm2;
createTiddlyText(img,lm2);
break;
case 'file':
var s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
var a = createTiddlyElement(s,'a');
a.href = w.tiddler.title + '/' + lm2;
createTiddlyText(a,lm2);
break;
case 'link':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createTiddlyElement(s,'a');
var t = w.tiddler ? w.tiddler.title + ':' : '';
a.setAttribute('href','#' + t + lm2);
a.title = 'section link';
createTiddlyText(a,lm2);
break;
case 'weblog':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
var text = lm2;
var link = 'Weblog: ' + lm2;
createTiddlyText(createTiddlyLink(s,link,false,null,w.isStatic),text);
break;
case 'section':
a = createTiddlyElement(w.output,'a');// drop anchor
t = w.tiddler ? w.tiddler.title + ':' : '';
a.setAttribute('name',t + lm2);
break;
case 'date':
createTiddlyText(w.output,lm2);
break;
case 'user':
var oldSource = w.source;
w.source = lm2;
w.nextMatch = 0;
w.subWikifyUnterm(w.output);
w.source = oldSource;
break;
// Shortcut expansions - not strictly syntax
case 'google':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createExternalLink(s,'http://www.google.com/search?q='+lm2);
createTiddlyText(a,lm2);
break;
case 'fedex':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createExternalLink(s,'http://www.fedex.com/Tracking?tracknumbers='+lm2);
createTiddlyText(a,lm2);
break;
case 'map':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createExternalLink(s,'http://maps.google.com/maps?q='+lm2);
createTiddlyText(a,lm2);
break;
case 'wikipedia':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createExternalLink(s,'http://en.wikipedia.org/wiki/'+lm2);
createTiddlyText(a,lm2);
break;
case 'rt':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createExternalLink(s,'http://rt.socialtext.net/Ticket/Display.html?id='+lm2);
createTiddlyText(a,lm2);
break;
case 'stcal':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createExternalLink(s,'https://calendar.socialtext.net:445/view_t.php?timeb=1&id=3&date='+lm2);
createTiddlyText(a,lm2);
break;
case 'svn':
s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
a = createExternalLink(s,'https://repo.socialtext.net/listing.php?rev='+lm2+'sc=1');
createTiddlyText(a,lm2);
break;
default:
w.outputText(w.output,w.matchStart,w.nextMatch);
return;
}
w.nextMatch = this.lookaheadRegExp.lastIndex;
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
};
SocialtextFormatter.presence = function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var p = lookaheadMatch[1];
var text = lookaheadMatch[2];
var link;
var src;
if(p=='aim') {
link = 'aim:goim?screenname=' + text + '&message=hello';
src = 'http://big.oscar.aol.com/sleepleft?on_url=http://www.aim.com/remote/gr/MNB_online.gif&off_url=http://www.aim.com/remote/gr/MNB_offline.gif';
} else if(p=='yahoo'||p=='ymsgr') {
link = 'ymsgr:sendIM?'+text;
src = 'http://opi.yahoo.com/online?u=chrislondonbridge&f=.gif';
} else if(p=='skype'||p=='callto') {
link = 'callto:'+text;
src = 'http://goodies.skype.com/graphics/skypeme_btn_small_green.gif';
} else if(p=='asap') {
link = 'http://asap2.convoq.com/AsapLinks/Meet.aspx?l='+text;
src = 'http://asap2.convoq.com/AsapLinks/Presence.aspx?l='+text;
}
var s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
var a = createExternalLink(s,link);
var img = createTiddlyElement(a,'img');
createTiddlyText(a,text);
img.src = src;
img.border='0';
img.alt = '(' + lookaheadMatch[1] + ')';
if(p=='aim') {
img.width='11'; img.height='13';
}
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
};
config.formatterHelpers.singleCharFormat = function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[0].substr(lookaheadMatch[0].length-2,1) != ' ') {
w.subWikifyTerm(createTiddlyElement(w.output,this.element),this.termRegExp);
} else {
w.outputText(w.output,w.matchStart,w.nextMatch);
}
};
config.socialtext = {};
config.socialtext.formatters = [
{
name: 'socialtextHeading',
match: '^\\^{1,6} ?',
termRegExp: /(\n+)/mg,
handler: function(w)
{
var len = w.matchText.trim().length;
var e = createTiddlyElement(w.output,'h' + len);
var a = createTiddlyElement(e,'a');// drop anchor
var t = w.tiddler ? w.tiddler.title + ':' : '';
len = w.source.substr(w.nextMatch).indexOf('\n');
a.setAttribute('name',t+w.source.substr(w.nextMatch,len));
w.subWikifyTerm(e,this.termRegExp);
}
},
{
name: 'socialtextTable',
match: '^\\|(?:(?:.|\n)*)\\|$',
lookaheadRegExp: /^\|(?:(?:.|\n)*)\|$/mg,
cellRegExp: /(?:\|(?:[^\|]*)\|)(\n|$)?/mg,
cellTermRegExp: /((?:\x20*)\|)/mg,
handler: function(w)
{
var table = createTiddlyElement(w.output,'table');
var rowContainer = createTiddlyElement(table,'tbody');
var prevColumns = [];
w.nextMatch = w.matchStart;
this.lookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
var r = this.rowHandler(w,createTiddlyElement(rowContainer,'tr'),prevColumns);
if(!r) {
w.nextMatch++;
break;
}
this.lookaheadRegExp.lastIndex = w.nextMatch;
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
}
},
rowHandler: function(w,e,prevColumns)
{
this.cellRegExp.lastIndex = w.nextMatch;
var cellMatch = this.cellRegExp.exec(w.source);
while(cellMatch && cellMatch.index == w.nextMatch) {
w.nextMatch++;
var cell = createTiddlyElement(e,'td');
w.subWikifyTerm(cell,this.cellTermRegExp);
if(cellMatch[1]) {
// End of row
w.nextMatch = this.cellRegExp.lastIndex;
return true;
}
// Cell
w.nextMatch--;
this.cellRegExp.lastIndex = w.nextMatch;
cellMatch = this.cellRegExp.exec(w.source);
}
return false;
}
},
{
name: 'socialtextList',
match: '^[\\*#]+ ',
lookaheadRegExp: /^([\*#])+ /mg,
termRegExp: /(\n+)/mg,
handler: function(w)
{
var stack = [w.output];
var currLevel = 0, currType = null;
var itemType = 'li';
w.nextMatch = w.matchStart;
this.lookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
var listType = lookaheadMatch[1] == '*' ? 'ul' : 'ol';
var listLevel = lookaheadMatch[0].length;
w.nextMatch += listLevel;
if(listLevel > currLevel) {
for(var i=currLevel; i<listLevel; i++) {
stack.push(createTiddlyElement(stack[stack.length-1],listType));
}
} else if(listLevel < currLevel) {
for(i=currLevel; i>listLevel; i--) {
stack.pop();
}
} else if(listLevel == currLevel && listType != currType) {
stack.pop();
stack.push(createTiddlyElement(stack[stack.length-1],listType));
}
currLevel = listLevel;
currType = listType;
var e = createTiddlyElement(stack[stack.length-1],itemType);
w.subWikifyTerm(e,this.termRegExp);
this.lookaheadRegExp.lastIndex = w.nextMatch;
lookaheadMatch = this.lookaheadRegExp.exec(w.source);
}
}
},
{
name: 'socialtextQuoteByLine',
match: '^>+',
lookaheadRegExp: /^>+/mg,
termRegExp: /(\n)/mg,
element: 'blockquote',
handler: function(w)
{
var stack = [w.output];
var currLevel = 0;
var newLevel = w.matchLength;
var i;
do {
if(newLevel > currLevel) {
for(i=currLevel; i<newLevel; i++) {
stack.push(createTiddlyElement(stack[stack.length-1],this.element));
}
} else if(newLevel < currLevel) {
for(i=currLevel; i>newLevel; i--) {
stack.pop();
}
}
currLevel = newLevel;
w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
createTiddlyElement(stack[stack.length-1],'br');
this.lookaheadRegExp.lastIndex = w.nextMatch;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
if(matched) {
newLevel = lookaheadMatch[0].length;
w.nextMatch += newLevel;
}
} while(matched);
}
},
{
name: 'socialtextRule',
match: '^----+$\\n+',
handler: function(w)
{
createTiddlyElement(w.output,'hr');
}
},
{
name: 'socialtextPreformatted',
match: '^\\.pre\\s*\\n',
lookaheadRegExp: /^.pre\s*\n((?:.|\n)*?)\n.pre\s*\n/mg,
element: 'pre',
handler: config.formatterHelpers.enclosedTextHelper
},
{
name: 'socialtextHtml',
match: '^\\.html',
lookaheadRegExp: /\.html((?:.|\n)*?)\.html/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
createTiddlyElement(w.output,'span').innerHTML = lookaheadMatch[1];
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: 'macro',
match: '<<',
lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
w.nextMatch = this.lookaheadRegExp.lastIndex;
invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
}
}
},
{
name: 'socialtextExplicitLink',
match: '(?:".*?" ?)?\\[',
lookaheadRegExp: /(?:\"(.*?)\" ?)?\[([^\]]*?)\]/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var link = lookaheadMatch[2];
var text = lookaheadMatch[1] ? lookaheadMatch[1] : link;
createTiddlyText(createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler),text);
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: 'socialtextExternalLink',
match: '(?:".*?" ?)?<[a-z]{2,8}:',
lookaheadRegExp: /(?:\"(.*?)\" ?)?<([a-z]{2,8}:.*?)>/mg,
imgRegExp: /\.(?:gif|ico|jpg|png)/g,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var link = lookaheadMatch[2];
var text = lookaheadMatch[1] ? lookaheadMatch[1] : link;
this.imgRegExp.lastIndex = 0;
if(this.imgRegExp.exec(link)) {
var img = createTiddlyElement(w.output,'img');
if(lookaheadMatch[1]) {
img.title = text;
}
img.alt = text;
img.src = link;
} else {
createTiddlyText(createExternalLink(w.output,link),text);
}
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: 'socialtextUrlLink',
match: config.textPrimitives.urlPattern,
handler: function(w)
{
w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch);
}
},
{
name: 'socialtextBold',
match: '\\*(?![\\s\\*])',
lookaheadRegExp: /\*(?!\s)(?:.*?)(?!\s)\*(?=[$\s\|\._\-,])/mg,
termRegExp: /((?!\s)\*(?=[$\s\|\.\-_,]))/mg,
element: 'strong',
handler: config.formatterHelpers.singleCharFormat
},
{
name: 'socialtextItalic',
match: '_(?![\\s_])',
lookaheadRegExp: /_(?!\s)(?:.*?)(?!\s)_(?=[$\s\|\.\*\-,])/mg,
termRegExp: /((?!\s)_(?=[$\s\|\.\*\-,]))/mg,
element: 'em',
handler: config.formatterHelpers.singleCharFormat
},
{
name: 'socialtextStrike',
match: '-(?![\\s\\-])',
lookaheadRegExp: /-(?!\s)(?:.*?)(?!\s)-(?=[$\s\|\.\*_,])/mg,
termRegExp: /((?!\s)-(?=[$\s\|\.\*_,]))/mg,
element: 'del',
handler: config.formatterHelpers.singleCharFormat
},
{
name: 'socialtextMonoSpaced',
match: '`(?![\\s`])',
lookaheadRegExp: /`(?!\s)(?:.*?)(?!\s)`(?=[$\s\.\*\-_,])/mg,
termRegExp: /((?!\s)`(?=[$\s\.\*\-_,]))/mg,
element: 'tt',
handler: config.formatterHelpers.singleCharFormat
},
{
name: 'socialtextParagraph',
match: '\\n{2,}',
handler: function(w)
{
createTiddlyElement(w.output,'p');
}
},
{
name: 'socialtextLineBreak',
match: '\\n',
handler: function(w)
{
createTiddlyElement(w.output,'br');
}
},
{
name: 'socialtextNoWiki',
match: '\\{\\{',
lookaheadRegExp: /\{\{((?:.|\n)*?)\}\}/mg,
element: 'span',
handler: config.formatterHelpers.enclosedTextHelper
},
{
name: 'socialtextTrademark',
match: '\\{tm\\}',
handler: function(w)
{
createTiddlyElement(w.output,'span').innerHTML = '™';
}
},
{
name: 'socialtextWafl',
match: '\\{(?:[a-z]{2,16}): ?.*?\\}',
lookaheadRegExp: /\{([a-z]{2,16}): ?(.*?)\}/mg,
handler: SocialtextFormatter.wafl
},
{
name: 'socialtextPresence',
match: '(?:aim|yahoo|ymsgr|skype|callto|asap):\\w+',
lookaheadRegExp: /(aim|yahoo|ymsgr|skype|callto|asap):(\w+)/mg,
handler: SocialtextFormatter.presence
},
{
name: 'socialtextMailTo',
match: '[\\w\.]+@[\\w]+\.[\\w\.]+',
lookaheadRegExp: /([\w\.]+@[\w]+\.[\w\.]+)/mg,
handler: function(w)
{
this.lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var text = lookaheadMatch[1];
createTiddlyText(createExternalLink(w.output,'mailto:'+text),text);
w.nextMatch = this.lookaheadRegExp.lastIndex;
}
}
},
{
name: 'socialtextHtmlEntitiesEncoding',
match: '&#?[a-zA-Z0-9]{2,8};',
handler: function(w)
{
createTiddlyElement(w.output,'span').innerHTML = w.matchText;
}
}
];
config.parsers.socialtextFormatter = new Formatter(config.socialtext.formatters);
config.parsers.socialtextFormatter.format = 'socialtext';
config.parsers.socialtextFormatter.formatTag = 'SocialtextFormat';
} // end of 'install only once'
//}}}
/***
|''Name:''|SocialtextAdaptorPlugin|
|''Description:''|Adaptor for moving and converting data to and from Socialtext Wikis|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com) and JeremyRuston (jeremy (at) osmosoft (dot) com)|
|''Source:''|http://www.martinswiki.com/#SocialtextAdaptorPlugin|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/adaptors/SocialtextAdaptorPlugin.js|
|''Version:''|0.5.1|
|''Date:''|Feb 25, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.2.0|
Socialtext REST documentation is at:
http://www.eu.socialtext.net/st-rest-docs/index.cgi?socialtext_rest_documentation
***/
//{{{
if(!version.extensions.SocialtextAdaptorPlugin) {
version.extensions.SocialtextAdaptorPlugin = {installed:true};
function SocialtextAdaptor()
{
this.host = null;
this.workspace = null;
return this;
}
SocialtextAdaptor.mimeType = 'text/x.socialtext-wiki';
SocialtextAdaptor.serverType = 'socialtext';
SocialtextAdaptor.serverParsingErrorMessage = "Error parsing result from server";
SocialtextAdaptor.errorInFunctionMessage = "Error in function SocialtextAdaptor.%0";
SocialtextAdaptor.prototype.setContext = function(context,userParams,callback)
{
if(!context) context = {};
context.userParams = userParams;
if(callback) context.callback = callback;
context.adaptor = this;
if(!context.host)
context.host = this.host;
if(!context.workspace && this.workspace)
context.workspace = this.workspace;
return context;
};
SocialtextAdaptor.doHttpGET = function(uri,callback,params,headers,data,contentType,username,password)
{
return doHttp('GET',uri,data,contentType,username,password,callback,params,headers);
};
SocialtextAdaptor.doHttpPOST = function(uri,callback,params,headers,data,contentType,username,password)
{
return doHttp('POST',uri,data,contentType,username,password,callback,params,headers);
};
SocialtextAdaptor.fullHostName = function(host)
{
if(!host)
return '';
if(!host.match(/:\/\//))
host = 'http://' + host;
if(host.substr(host.length-1) != '/')
host = host + '/';
return host;
};
SocialtextAdaptor.minHostName = function(host)
{
return host ? host.replace(/^http:\/\//,'').replace(/\/$/,'') : '';
};
// Convert a page title to the normalized form used in uris
SocialtextAdaptor.normalizedTitle = function(title)
{
var n = title.toLowerCase();
n = n.replace(/\s/g,'_').replace(/\//g,'_').replace(/\./g,'_').replace(/:/g,'').replace(/\?/g,'');
if(n.charAt(0)=='_')
n = n.substr(1);
return String(n);
};
// Convert a Socialtext date in YYYY-MM-DD hh:mm format into a JavaScript Date object
SocialtextAdaptor.dateFromEditTime = function(editTime)
{
var dt = editTime;
return new Date(Date.UTC(dt.substr(0,4),dt.substr(5,2)-1,dt.substr(8,2),dt.substr(11,2),dt.substr(14,2)));
};
SocialtextAdaptor.prototype.openHost = function(host,context,userParams,callback)
{
this.host = SocialtextAdaptor.fullHostName(host);
context = this.setContext(context,userParams,callback);
if(context.callback) {
context.status = true;
window.setTimeout(function() {callback(context,userParams);},0);
}
return true;
};
SocialtextAdaptor.prototype.openWorkspace = function(workspace,context,userParams,callback)
{
this.workspace = workspace;
context = this.setContext(context,userParams,callback);
if(context.callback) {
context.status = true;
window.setTimeout(function() {callback(context,userParams);},0);
}
return true;
};
SocialtextAdaptor.prototype.getWorkspaceList = function(context,userParams,callback)
{
context = this.setContext(context,userParams,callback);
var uriTemplate = '%0data/workspaces';
var uri = uriTemplate.format([context.host]);
var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getWorkspaceListCallback,context,{'accept':'application/json'});
return typeof req == 'string' ? req : true;
};
SocialtextAdaptor.getWorkspaceListCallback = function(status,context,responseText,uri,xhr)
{
context.status = false;
context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getWorkspaceListCallback']);
if(status) {
try {
eval('var info=' + responseText);
} catch (ex) {
context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
if(context.callback)
context.callback(context,context.userParams);
return;
}
var list = [];
for(var i=0; i<info.length; i++) {
var item = {
title:info[i].title,
name:info[i].name,
modified:SocialtextAdaptor.dateFromEditTime(info[i].modified_time)
};
list.push(item);
}
context.workspaces = list;
context.status = true;
} else {
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
SocialtextAdaptor.prototype.getTiddlerList = function(context,userParams,callback)
{
context = this.setContext(context,userParams,callback);
var uriTemplate = '%0data/workspaces/%1/pages?order=newest';//!! ? or ;
var uri = uriTemplate.format([context.host,context.workspace]);
var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerListCallback,context,{'accept':'application/json'});
return typeof req == 'string' ? req : true;
};
SocialtextAdaptor.getTiddlerListCallback = function(status,context,responseText,uri,xhr)
{
context.status = false;
context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getTiddlerListCallback']);
if(status) {
try {
eval('var info=' + responseText);
} catch (ex) {
context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
if(context.callback)
context.callback(context,context.userParams);
return;
}
var list = [];
for(var i=0; i<info.length; i++) {
var tiddler = new Tiddler(info[i].name);
tiddler.modified = SocialtextAdaptor.dateFromEditTime(info[i].last_edit_time);
tiddler.modifier = info[i].last_editor;
tiddler.tags = info[i].tags;
tiddler.fields['server.page.id'] = info[i].page_id;
tiddler.fields['server.page.name'] = info[i].name;
tiddler.fields['server.page.revision'] = String(info[i].revision_id);
list.push(tiddler);
}
context.tiddlers = list;
context.status = true;
} else {
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
SocialtextAdaptor.prototype.generateTiddlerInfo = function(tiddler)
{
var info = {};
var host = this && this.host ? this.host : SocialtextAdaptor.fullHostName(tiddler.fields['server.host']);
var workspace = this && this.workspace ? this.workspace : tiddler.fields['server.workspace'];
uriTemplate = '%0%1/index.cgi?%2';
info.uri = uriTemplate.format([host,workspace,SocialtextAdaptor.normalizedTitle(tiddler.title)]);
return info;
};
SocialtextAdaptor.prototype.getTiddler = function(title,context,userParams,callback)
{
return this.getTiddlerRevision(title,null,context,userParams,callback);
};
SocialtextAdaptor.prototype.getTiddlerRevision = function(title,revision,context,userParams,callback)
{
context = this.setContext(context,userParams,callback);
// request the page in json format to get the page attributes
if(revision) {
var uriTemplate = '%0data/workspaces/%1/pages/%2/revisions/%3';
context.revision = revision;
} else {
uriTemplate = '%0data/workspaces/%1/pages/%2';
context.revision = null;
}
uri = uriTemplate.format([context.host,context.workspace,SocialtextAdaptor.normalizedTitle(title),revision]);
context.tiddler = new Tiddler(title);
context.tiddler.fields.wikiformat = 'socialtext';
context.tiddler.fields['server.host'] = SocialtextAdaptor.minHostName(context.host);
context.tiddler.fields['server.workspace'] = context.workspace;
var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerCallback,context,{'accept':'application/json'});
return typeof req == 'string' ? req : true;
};
SocialtextAdaptor.getTiddlerCallback = function(status,context,responseText,uri,xhr)
{
context.status = false;
context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getTiddlerCallback']);
if(status) {
try {
eval('var info=' + responseText);
context.tiddler.tags = info.tags;
context.tiddler.fields['server.page.id'] = info.page_id;
context.tiddler.fields['server.page.name'] = info.name;
context.tiddler.fields['server.page.revision'] = String(info.revision_id);
context.tiddler.modifier = info.last_editor;
context.tiddler.modified = SocialtextAdaptor.dateFromEditTime(info.last_edit_time);
} catch (ex) {
context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
if(context.callback)
context.callback(context,context.userParams);
return;
}
context.status = true;
} else {
context.statusText = xhr.statusText;
if(context.callback)
context.callback(context,context.userParams);
return;
}
var uriTemplate = context.revision ? '%0data/workspaces/%1/pages/%2/revisions/%3' : '%0data/workspaces/%1/pages/%2';
var host = SocialtextAdaptor.fullHostName(context.tiddler.fields['server.host']);
var workspace = context.workspace ? context.workspace : context.tiddler.fields['server.workspace'];
uri = uriTemplate.format([host,workspace,SocialtextAdaptor.normalizedTitle(context.tiddler.title),context.revision]);
var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerCallback2,context,{'accept':SocialtextAdaptor.mimeType});
};
SocialtextAdaptor.getTiddlerCallback2 = function(status,context,responseText,uri,xhr)
{
context.tiddler.text = responseText;
if(status) {
context.status = true;
} else {
context.status = false;
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
SocialtextAdaptor.prototype.getTiddlerRevisionList = function(title,limit,context,userParams,callback)
{
context = this.setContext(context,userParams,callback);
var uriTemplate = '%0data/workspaces/%1/pages/%2/revisions?accept=application/json';
if(!limit)
limit = 5;
var uri = uriTemplate.format([context.host,context.workspace,SocialtextAdaptor.normalizedTitle(title),limit]);
var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerRevisionListCallback,context);
return typeof req == 'string' ? req : true;
};
SocialtextAdaptor.getTiddlerRevisionListCallback = function(status,context,responseText,uri,xhr)
{
context.status = false;
if(status) {
var content = null;
try {
eval('var info=' + responseText);
} catch (ex) {
context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
if(context.callback)
context.callback(context,context.userParams);
return;
}
list = [];
for(var i=0; i<info.length; i++) {
var tiddler = new Tiddler(info[i].name);
tiddler.modified = SocialtextAdaptor.dateFromEditTime(info[i].last_edit_time);
tiddler.modifier = info[i].last_editor;
tiddler.tags = info[i].tags;
tiddler.fields['server.page.id'] = info[i].page_id;
tiddler.fields['server.page.name'] = info[i].name;
tiddler.fields['server.page.revision'] = info[i].revision_id;
list.push(tiddler);
}
var sortField = 'server.page.revision';
list.sort(function(a,b) {return a.fields[sortField] < b.fields[sortField] ? +1 : (a.fields[sortField] == b.fields[sortField] ? 0 : -1);});
context.revisions = list;
context.status = true;
} else {
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
SocialtextAdaptor.prototype.putTiddler = function(tiddler,context,userParams,callback)
{
context = this.setContext(context,userParams,callback);
context.tiddler = tiddler;
context.title = tiddler.title;
var uriTemplate = '%0data/workspaces/%1/pages/%2';
var host = context.host ? context.host : SocialtextAdaptor.fullHostName(tiddler.fields['server.host']);
var workspace = context.workspace ? context.workspace : tiddler.fields['server.workspace'];
var uri = uriTemplate.format([host,workspace,tiddler.title,tiddler.text]);
//var req = doHttp('POST',uri,tiddler.text,SocialtextAdaptor.mimeType,null,null,SocialtextAdaptor.putTiddlerCallback,context,{"X-Http-Method": "PUT"});
var req = SocialtextAdaptor.doHttpPOST(uri,SocialtextAdaptor.putTiddlerCallback,context,{"X-Http-Method": "PUT"},tiddler.text,SocialtextAdaptor.mimeType);
return typeof req == 'string' ? req : true;
};
SocialtextAdaptor.putTiddlerCallback = function(status,context,responseText,uri,xhr)
{
if(status) {
context.status = true;
} else {
context.status = false;
context.statusText = xhr.statusText;
}
if(context.callback)
context.callback(context,context.userParams);
};
SocialtextAdaptor.prototype.close = function()
{
return true;
};
config.adaptors[SocialtextAdaptor.serverType] = SocialtextAdaptor;
} //# end of 'install only once'
//}}}
/***
SocialtextStyleOverrides
***/
/*{{{*/
.headerShadow {padding: 2em 0em .5em 1em;}
.headerForeground {padding: 2em 0em .5em 1em;}
#st-page-wiki-title {
font-size: 80%;
}
.subtitle {
font-style: italic;
font-size 80%;
}
/* from #st-tags */
.tagged {
border-color: #bbeebb;
background-color: #f4fff4;
}
.tagged .listTitle {
color: #595;
font-weight: bold;
}
.tagged .button {
color: #000;
}
.selected .tagged {
background-color: ColorPalette::TertiaryLight;
border: 1px solid ColorPalette::TertiaryMid;
}
/* from #st-incoming-links */
.tagging {
border-color: #ebb;
background-color: #fff4f4;
}
.tagging .listTitle {
color: #b78;
font-weight: bold;
}
.tagging .button {
color: #999;
}
.selected .tagging {
background-color: ColorPalette::TertiaryLight;
border: 1px solid ColorPalette::TertiaryMid;
}
.tiddler {/* Tiddler body */
border:1px solid #ccc;
margin:0.5em;
background:#fff;
padding:0.5em;
}
.viewer blockquote {border-left: 0px solid}
.tiddlyLinkNonExisting {
font-style: italic;
border-bottom: 1px dashed;
}
.editor input, .editor textarea {
background: #ffd;
border-style: solid;
border-color: #888 #ccc #ccc #888;
border-width: 2px;
}
.tabContents {white-space: nowrap;}
#displayArea {margin: 1em 20em 0em 14em;}
#sidebar {
position: absolute;
right: 3px;
width: 21em;
font-size: .9em;
}
#sidebarOptions .button {
border-color: #eee;
}
#sidebarTabs .tabContents {
width: 20em;
overflow: hidden;
}
.viewer tt {
font-size: 1.2em;
line-height: 1.4em;
}
ul {list-style-type: square;}
ul ul {list-style-type: circle;}
ol {list-style-type: decimal;}
ol ol {list-style-type: decimal;}
ol ol ol {list-style-type: decimal;}
ol ol ol ol {list-style-type: decimal;}
ol ol ol ol ol {list-style-type: decimal;}
ol ol ol ol ol ol {list-style-type: decimal;}
/*}}}*/
/***
SocialtextScreenStyle
http://www.eu.socialtext.net/static/2.0.0.1/css/st/screen.css
***/
/*{{{*/
body {
font-family: Arial, sans-serif;
color: #000;
background: #eee;
margin: 0;
}
/* Wiki Navigation */
.st-wiki-nav {
clear: both;
margin-left: 10px;
margin-right: 10px;
}
.st-wiki-nav-content {
background: url('../../images/st/wiki-nav/solid.gif') repeat-x left bottom;
margin-left: 24px;
margin-right: 24px;
padding-top: 3px;
min-height: 24px;
}
* html .st-wiki-nav-content {
padding-bottom: 3px;
height: 24px;
}
.st-wiki-nav-right {
background: url('../../images/st/wiki-nav/right-round.gif') no-repeat bottom right;
}
.st-wiki-nav-left {
background: url('../../images/st/wiki-nav/left-round.gif') no-repeat bottom left;
}
#st-home {
float: left;
margin-right: 60px;
padding-top: 2px;
}
#st-home-link {
color: white;
text-decoration: none;
font-weight: bold;
font-family: Helvetica, sans-serif;
font-size: 90%;
}
#st-editing-prefix-container {
border-collapse: collapse;
width: 100%;
padding: 0px;
margin: 0px;
margin-bottom: -20px;
}
#st-editing-prefix-container tr td {
margin: 0px;
padding: 0px;
}
#st-editing-title {
color: black;
background-color: white;
text-decoration: none;
font-weight: bold;
font-family: Helvetica, sans-serif;
font-size: 90%;
margin-bottom: 0.4em;
}
#st-wiki-title-invite {
font-size: 50%;
font-family: Helvetica, sans-serif;
}
#st-wiki-title-central-page-link {
font-size: 50%;
font-family: Helvetica, sans-serif;
}
#st-wiki-title-invite a {
color: #00f;
}
#st-wiki-logo {
text-align: center;
clear: both;
}
#st-wiki-logo-image {
}
.st-wiki-nav-actions {
float: right;
color: black;
font-size: 75%;
padding-top: 3px;
}
.st-wiki-nav-actions a {
padding: 2px;
color: white;
text-decoration: none;
font-family: Helvetica, sans-serif;
}
/* Wiki Subnav */
#st-wiki-subnav {
margin-top: 2px;
font-size: 70%;
font-weight: bold;
font-family: Helvetica, sans-serif;
color: #888;
}
#st-wiki-subnav a {
padding: 2px;
color: #008;
text-decoration: none;
}
#st-wiki-subnav-right {
float: right;
margin-right: 6em;
}
#st-wiki-subnav-left {
float: left;
margin-left: 6em;
}
* html #st-wiki-subnav-left {
margin-left: 3em;
}
/* Wiki Navigation Search Bar */
#st-search-form {
margin: 0;
padding: 0;
padding-top: 1px;
}
#st-search-form .button-table {
float: left;
font-size: 79%;
font-weight: bold;
margin-left: 5px;
margin-top: 1px;
}
#st-search-form #st-search-term {
float: left;
font-size: 60%;
}
/* Content Outline */
#st-content-border, #st-edit-border {
position: relative;
clear: both;
margin-left: 3px;
margin-right: 2px;
margin-bottom: 0px;
margin-top: 0px;
border-bottom: 1px solid #eee;
}
#st-content-border-left, #st-edit-border-left {
background: url('../../images/st/page-shadow/left.gif') left top repeat-y;
position: relative;
}
#st-content-border-right, #st-edit-border-right {
background: url('../../images/st/page-shadow/right.gif') right top repeat-y;
position: relative;
}
#st-content-border-top, #st-edit-border-top {
position: relative;
background: url('../../images/st/page-shadow/top.gif') left top repeat-x;
}
#st-content-border-bottom, #st-edit-border-bottom {
background: url('../../images/st/page-shadow/bottom.gif') left bottom repeat-x;
position: relative;
}
#st-content-border-left-top, #st-edit-border-left-top {
background: url('../../images/st/page-shadow/left-top.gif') left top no-repeat;
position: relative;
}
#st-content-border-right-top, #st-edit-border-right-top {
background: url('../../images/st/page-shadow/right-top.gif') right top no-repeat;
position: relative;
}
#st-content-border-left-bottom, #st-edit-border-left-bottom {
background: url('../../images/st/page-shadow/left-bottom.gif') left bottom no-repeat;
position: relative;
}
#st-content-border-right-bottom, #st-edit-border-right-bottom {
background: url('../../images/st/page-shadow/right-bottom.gif') right bottom no-repeat;
padding-top: 5px;
padding-bottom: 9px;
position: relative;
}
* html #st-content-border-right-bottom, * html #st-edit-border-right-bottom {
padding-top: 4px;
padding-left: 7px;
padding-right: 8px;
position: relative;
}
.st-content-width-controller {
width: 100%;
position: relative;
border-collapse: collapse;
}
.st-content-width-controller td {
vertical-align: top;
}
.st-content {
position: relative;
background-color: white;
margin-top: 0px;
margin-left: 7px;
margin-right: 8px;
margin-bottom: -1px;
border-left: 1px dotted #80a9f3;
border-right: 1px dotted #80a9f3;
border: 1px solid #80a9f3;
padding: 6px 12px 12px 12px;
}
* html .st-content {
margin-top: 0px;
margin-left: 0px;
margin-right: 0px;
}
/* This textarea is only for Safari. However, if we use display:none; here Safari ignores the .value operation in JS */
#st-raw-wikitext-textarea {
width:1px;
height:1px;
margin:0;
padding:0;
}
/* Action Buttons */
.button-table, .button-table tr td {
border-collapse: collapse;
margin: 0;
padding: 0;
}
.button-rounded {
background: url('../../images/st/grey-button/left-top-rounded.png') top left no-repeat;
margin: 0;
}
.button-rounded-right-top {
background: url('../../images/st/grey-button/right-top-rounded.png') top right no-repeat;
margin: 0;
}
.button-rounded-left-bottom {
background: url('../../images/st/grey-button/left-bottom-rounded.png') bottom left no-repeat;
margin: 0;
}
.button-rounded-right-bottom {
background: url('../../images/st/grey-button/right-bottom-rounded.png') bottom right no-repeat;
margin: 0;
}
.button-straight {
background: url('../../images/st/grey-button/left-top-straight.png') top left no-repeat;
margin: 0;
}
.button-straight-right-top {
background: url('../../images/st/grey-button/right-top-straight.png') top right no-repeat;
margin: 0;
}
.button-straight-left-bottom {
background: url('../../images/st/grey-button/left-bottom-straight.png') bottom left no-repeat;
margin: 0;
}
.button-straight-right-bottom {
background: url('../../images/st/grey-button/right-bottom-straight.png') bottom right no-repeat;
margin: 0;
}
.button-content {
font-size: 90%;
}
.button-content a {
display: block;
padding: 2px;
padding-left: 10px;
padding-right: 10px;
font-family: Helvetica, Verdana, sans-serif;
font-weight: bold;
text-decoration: none;
color: black;
}
.button-content input.submit {
border: 0px;
padding: 2px;
padding-left: 10px;
padding-right: 10px;
font-family: Helvetica, Verdana, sans-serif;
font-weight: bold;
text-decoration: none;
color: black;
background-color: transparent;
}
/* Personal Homepage */
#st-homepage {
background: white url('../../images/st/homepage/blue-fade.gif') top left no-repeat;
}
#st-homepage-layout {
margin-top: 15px;
clear: both;
width: 100%;
border-collapse: collapse;
}
#st-homepage-layout tr td.st-homepage-layout-cell {
padding: 5px;
vertical-align: top;
}
#st-homepage-layout-dashboard {
width: 50%
}
#st-homepage-layout-notes {
width: 50%;
}
#st-homepage-notes, #st-homepage-dashboard {
text-align: left;
width: 95%;
}
#st-user-greeting, #st-wiki-title {
font-family: Helvetica, Verdana, sans-serif;
font-size: 150%;
}
#st-wiki-title {
margin-left: 5px;
}
#st-user-greeting {
position: relative;
text-align: right;
float: right;
}
#st-group-notes-content, #st-personal-notes-content {
}
.st-homepage-section {
margin-bottom: 15px;
}
#st-homepage-notes .st-homepage-section {
background-color: white;
border: 1px solid #aaa;
padding: 15px;
}
.st-homepage-section-title {
font-size: 110%;
font-family: Helvetica, Verdana, sans-serif;
}
#st-homepage-notes .st-homepage-section-title {
color: #aaa;
text-decoration: underline;
}
.st-homepage-notes-edit-link {
background: url('../../images/st/homepage/edit-icon.gif') no-repeat left top;
display: block;
text-indent: -2000px;
height: 13px;
width: 36px;
text-decoration: none;
padding:0;
}
* html .st-homepage-notes-edit-link {
border:1px solid white;
}
.st-homepage-notes-edit {
font-family: Verdana, sans-serif;
font-size: 65%;
float: right;
}
.st-homepage-notes-content {
font-size: 85%;
margin-top: 10px;
padding-top: 0px;
padding-bottom: 0px;
font-family: Verdana, Helvetica, sans-serif;
}
#st-dyk {
border-color: #cca !important;
background-color: #ffe !important;
}
#st-dyk-title {
color: #e4a020 !important;
text-decoration: none !important;
}
/* Homepage Simple List */
#st-whats-new-title-link {
background: url('../../images/st/homepage/icon-28-pages.gif') no-repeat left top;
}
#st-watchlist-title-link {
background: url('../../images/st/homepage/icon-28-star.gif') no-repeat left top;
}
#st-wikis-title-link {
background: url('../../images/st/homepage/icon-28-group.gif') no-repeat left top;
}
.st-homepage-simplelist-title-link {
display: block;
padding-left: 32px;
min-height: 32px;
}
* html .st-homepage-simplelist-title-link {
height: 32px;
}
.st-homepage-simplelist-title {
}
.st-homepage-simplelist-table {
margin-left: 25px;
border: 1px dashed #ddd;
border-collapse: collapse;
font-family: Verdana, Helvetica, sans-serif;
font-size: 80%;
width: 95%;
}
.st-homepage-simplelist-table td {
padding: 2px;
}
.st-homepage-simplelist-table tr.st-homepage-simplelist-row-odd {
background-color: #f3f7f7;
}
.st-homepage-simplelist-table tr.st-homepage-simplelist-row-even {
background-color: white;
}
.st-homepage-simplelist-table a {
color: #4f55dd;
text-decoration: none;
}
.st-homepage-simplelist-table a:visited {
color: #551a8b;
}
.st-homepage-simplelist-subleft {
font-size: 80%;
margin-left: 1em;
color: #666;
}
.st-homepage-simplelist-right {
width: 20%;
}
.st-homepage-simplelist-subright {
font-size: 80%;
color: #666;
}
.st-homepage-simplelist {
}
.st-homepage-simplelist-header {
min-height: 35px;
}
.st-homepage-simplelist-header .button-table {
float: right;
margin-right: 15px;
font-size: 95%;
}
.st-homepage-simplelist-header .button-table .button-content {
padding: 1px;
}
.st-homepage-whatsnew-author, .st-homepage-whatsnew-date {
color: #555;
}
.st-homepage-whatsnew-attribution {
padding-left: 1em;
font-size: 80%;
color: #aaa;
}
/* Homepage Wikis List */
#st-wikis-title {
}
/* Data and Templates */
.st-jst-template, .st-json {
display: none;
}
/* Page Sidebox Common Styles */
#st-page-boxes-toggle {
position: relative;
float: right;
text-align: right;
font-family: Verdana, Arial, sans-serif;
font-weight: bold;
font-size: 80%;
margin-bottom: 0.7em;
}
#st-page-boxes-toggle-link {
text-decoration: none;
}
#st-page-boxes-underlay {
float: right;
margin-top: -10px;
margin-right: 10px;
background: white;
z-index: 198;
clear: both;
margin-left: 15px;
}
* html #st-page-boxes-underlay {
margin-right: 4px;
}
#st-page-boxes {
background: inherit;
position: absolute;
right: 23px;
z-index: 199;
margin-top: 15px;
margin-left: 20px;
}
#st-page-boxes, #st-page-boxes-underlay {
width: 225px;
/* padding-left: 15px; */ /* Gives the white border effect, cwest dislikes it. */
}
.st-page-box {
border: 1px solid black;
padding: 5px;
font-family: Verdana, Helvetica, sans-serif;
font-size: 80%;
margin-top: 15px;
}
.st-page-box-title {
font-family: Helvetica, Verdana, sans-serif;
font-weight: bold;
margin-bottom: 10px;
}
.st-page-box-listing {
margin: 0;
padding: 0;
}
.st-page-box-listing-entry {
display: block;
}
.st-page-boxes-nobacklinks {
font-family: Verdana, Helvetica, sans-serif;
font-size: 90%;
color: #888;
}
.st-page-box-first {
margin-top: 0px;
}
/* Page Display */
#st-page-content {
clear: left;
margin-top: 6px;
margin-bottom: 0;
padding-bottom: 0;
}
#st-page-content, #st-page-content td {
font-family: Verdana, Helvetica, sans-serif;
font-size: 90%;
}
#st-page-wiki-title {
font-family: Helvetica, Verdana, sans-serif;
font-size: 65%;
font-weight: bold;
color: #aaa;
margin-bottom: 0.2em;
margin-top: 0.1em;
padding-top: 0;
}
#wiki {
margin: 0;
padding: 0;
}
#st-page-title {
}
#st-page-titletext, .st-page-title {
font-family: Helvetica, Verdana, sans-serif;
font-size: 150%;
font-weight: bold;
color: #888;
border-bottom: 1px solid #888;
}
#st-newpage-pagename-edit {
font-family: inherit;
font-size: inherit;
font-weight: inherit;
color: #000;
border: 1px solid black;
padding-left: 0.3em;
background-color: #ffd;
}
#st-page-details {
font-style: italic;
font-size: 75%;
font-family: Georgia, serif;
margin: 6px 10px 0 10px;
}
#st-page-details-feed-icon {
vertical-align: middle;
border: none;
}
#st-page-stats {
float: right;
vertical-align: middle;
}
#st-attribution {
float: left;
margin-bottom: 10px;
}
#st-page-editing-wysiwyg {
background: #ffd;
border-style: solid;
border-color: #888 #ccc #ccc #888;
border-width: 2px;
width: 100%;
}
#st-page-editing-toolbar {
margin-left: -6px;
overflow: hidden;
float: left;
height: 25px;
}
#wikiwyg_wikitext_textarea {
margin-top: 4px;
background: #ffd;
border-style: solid;
border-color: #888 #ccc #ccc #888;
border-width: 2px;
width: 100%;
font-family: monospace;
}
#st-page-maincontent {
}
#st-page-editing, #wikiwyg_wikitext_textarea {
}
#st-page-editing-pagebody-decoy, #st-page-editing-wysiwyg {
display: none;
}
#st-editing-tools-edit {
display: none;
}
#st-mode-wysiwyg-button
{
font-size: 70%;
margin-left: 4em;
}
#st-mode-wikitext-button
{
font-size: 70%;
}
#st-edit-tips
{
font-size: 70%;
}
.wikiwyg_button {
background: #FFFFFF;
border: 1px solid #FFFFFF;
cursor: pointer;
width: 20px;
height: 20px;
vertical-align: bottom;
}
.wikiwyg_button:hover {
border: 1px outset;
}
.wikiwyg_button:active {
border: 1px inset;
}
#wikiwyg_toolbar {
display: none;
}
/* Sidebox Pagetools: Revisions, Watchlist */
#st-side-box-pagetools {
border-collapse: collapse;
}
#st-rewind-norevisions {
font-family: Helvetica, Arial, sans-serif;
font-size: 11px;
color: #777;
text-decoration: none;
}
#st-side-box-pagetools a {
font-family: Helvetica, Arial, sans-serif;
font-size: 11px;
color: #555;
text-decoration: none;
}
/* Page View Tags/Incoming Links Sidebox */
#st-tags {
background: #f4fff4;
border-color: #bbeebb;
color: #999;
}
#st-tags-title {
color: #595;
}
#st-tags-addlink, #st-tags-addbutton {
font-weight: bold;
}
#st-tags-listing {
margin-bottom: 5px;
}
#st-tags-addinput, #st-tags-message, #st-tags-suggestion {
display: none;
}
#st-tags-deletemessage {
font-size: 90%;
color: #555;
display: none;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
#st-tags-suggestion {
margin-top: 2px;
}
.st-tags-level1 {
font-size: 90%;
}
.st-tags-level2 {
font-size: 100%;
}
.st-tags-level3 {
font-size: 110%;
}
.st-tags-level4 {
font-size: 120%;
}
.st-tags-level5 {
font-size: 130%;
}
.st-tags-tagline .st-tags-tagdelete {
text-decoration: none;
color: #ccc;
}
.st-tags-tagline a {
text-decoration: none;
color: #444;
}
#st-tags-field {
width: 95%;
}
#st-incoming-links {
border-color: #ebb;
background-color: #fff4f4;
}
#st-incoming-links-title {
color: #b78;
}
#st-attachments {
border-color: #bbe;
background-color: #f4f4ff;
}
#st-attachments-uploadbutton, #st-attachments-managebutton {
}
#st-attachments-buttons-uploadbutton {
margin: 0px;
padding: 0px;
padding-left: 2px;
}
#st-attachments-buttons-managebutton {
margin: 0px;
padding: 0px;
padding-right: 2px;
}
#st-attachments-buttons td {
padding-right: 3px;
font-size: 99%;
}
#st-attachments-buttons {
border-collapse: collapse;
margin: 0px;
padding: 0px;
margin-top: 5px;
}
#st-attachments-title {
color: #77b;
}
.st-attachments-line {
width:100%;
overflow:hidden;
}
/* Actions Bar */
#st-actions-bar-spacer {
clear:both;
height:0.5em;
overflow:hidden;
}
#st-actions-bar-spacer-clear {
clear:both;
height:1px;
overflow:hidden;
}
#st-actions-bar, #st-editing-tools-bar {
margin-left: 30px !important;
margin-right: 30px !important;
}
/* Footer */
#st-footer {
margin-top: -8px;
margin-bottom: 5px;
clear: both;
}
/* Socialtext Attribution */
#st-socialtext-attribution {
clear: both;
text-align: center;
font-size: 80%;
font-family: Helvetica, sans-serif;
}
#st-socialtext-attribution-link {
text-decoration: none;
}
#st-socialtext-attribution-image {
border: 0;
}
/* Page Actions */
#st-edit-button-border-left-middle, #st-login-to-edit-button-border-left-middle {
background: url('../../images/st/button-blue/left-middle.gif') left top repeat-y;
}
#st-edit-button-border-right-middle, #st-login-to-edit-button-border-right-middle {
background: url('../../images/st/button-blue/right-middle.gif') right top repeat-y;
}
#st-edit-button-border-left-top, #st-login-to-edit-button-border-left-top {
background: url('../../images/st/button-blue/left-top.gif') left top no-repeat;
}
#st-edit-button-border-right-top, #st-login-to-edit-button-border-right-top {
background: url('../../images/st/button-blue/right-top.gif') right top no-repeat;
}
#st-edit-button-border-left-bottom, #st-login-to-edit-button-border-left-bottom {
background: url('../../images/st/button-blue/left-bottom.gif') left bottom no-repeat;
}
#st-edit-button-border-right-bottom, #st-login-to-edit-button-border-right-bottom {
background: url('../../images/st/button-blue/right-bottom.gif') right bottom no-repeat;
}
#st-edit-button-link, #st-login-to-edit-button-link {
}
#st-comment-button-border-left-middle {
background: url('../../images/st/button-purple/left-middle.gif') left top repeat-y;
}
#st-comment-button-border-right-middle {
background: url('../../images/st/button-purple/right-middle.gif') right top repeat-y;
}
#st-comment-button-border-left-top {
background: url('../../images/st/button-purple/left-top.gif') left top no-repeat;
}
#st-comment-button-border-right-top {
background: url('../../images/st/button-purple/right-top.gif') right top no-repeat;
}
#st-comment-button-border-left-bottom {
background: url('../../images/st/button-purple/left-bottom.gif') left bottom no-repeat;
}
#st-comment-button-border-right-bottom {
background: url('../../images/st/button-purple/right-bottom.gif') right bottom no-repeat;
}
#st-comment-button-link {
}
#st-save-button-border-left-middle {
background: url('../../images/st/button-green/left-middle.gif') left top repeat-y;
}
#st-save-button-border-right-middle {
background: url('../../images/st/button-green/right-middle.gif') right top repeat-y;
}
#st-save-button-border-left-top {
background: url('../../images/st/button-green/left-top.gif') left top no-repeat;
}
#st-save-button-border-right-top {
background: url('../../images/st/button-green/right-top.gif') right top no-repeat;
}
#st-save-button-border-left-bottom {
background: url('../../images/st/button-green/left-bottom.gif') left bottom no-repeat;
}
#st-save-button-border-right-bottom {
background: url('../../images/st/button-green/right-bottom.gif') right bottom no-repeat;
}
#st-save-button-link {
}
#st-preview-button-border-left-middle {
background: url('../../images/st/button-gold/left-middle.gif') left top repeat-y;
}
#st-preview-button-border-right-middle {
background: url('../../images/st/button-gold/right-middle.gif') right top repeat-y;
}
#st-preview-button-border-left-top {
background: url('../../images/st/button-gold/left-top.gif') left top no-repeat;
}
#st-preview-button-border-right-top {
background: url('../../images/st/button-gold/right-top.gif') right top no-repeat;
}
#st-preview-button-border-left-bottom {
background: url('../../images/st/button-gold/left-bottom.gif') left bottom no-repeat;
}
#st-preview-button-border-right-bottom {
background: url('../../images/st/button-gold/right-bottom.gif') right bottom no-repeat;
}
#st-preview-button-link {
}
#st-cancel-button-border-left-middle {
background: url('../../images/st/button-crimson/left-middle.gif') left top repeat-y;
}
#st-cancel-button-border-right-middle {
background: url('../../images/st/button-crimson/right-middle.gif') right top repeat-y;
}
#st-cancel-button-border-left-top {
background: url('../../images/st/button-crimson/left-top.gif') left top no-repeat;
}
#st-cancel-button-border-right-top {
background: url('../../images/st/button-crimson/right-top.gif') right top no-repeat;
}
#st-cancel-button-border-left-bottom {
background: url('../../images/st/button-crimson/left-bottom.gif') left bottom no-repeat;
}
#st-cancel-button-border-right-bottom {
background: url('../../images/st/button-crimson/right-bottom.gif') right bottom no-repeat;
}
#st-cancel-button-link {
}
#st-edit-more-button-border-left-middle {
background: url('../../images/st/button-blue/left-middle.gif') left top repeat-y;
}
#st-edit-more-button-border-right-middle {
background: url('../../images/st/button-blue/right-middle.gif') right top repeat-y;
}
#st-edit-more-button-border-left-top {
background: url('../../images/st/button-blue/left-top.gif') left top no-repeat;
}
#st-edit-more-button-border-right-top {
background: url('../../images/st/button-blue/right-top.gif') right top no-repeat;
}
#st-edit-more-button-border-left-bottom {
background: url('../../images/st/button-blue/left-bottom.gif') left bottom no-repeat;
}
#st-edit-more-button-border-right-bottom {
background: url('../../images/st/button-blue/right-bottom.gif') right bottom no-repeat;
}
#st-edit-more-button-link {
}
.st-page-action-button-link {
min-height: 24px;
min-width: 100px;
text-align: center;
font-family: Helvetica, Verdana, sans-serif;
font-size: 90%;
text-decoration: none;
color: #fff;
font-weight: bold;
display: block;
padding-top: 8px;
padding-bottom: 0px;
margin-bottom: -3px;
width: 100%;
margin-left: -2px;
}
* html .st-page-action-button-link {
padding-top: 5px;
padding-bottom: 0px;
height: 24px;
}
.st-page-action-button {
float: left;
margin: 0;
padding: 0;
margin-right: 10px;
min-height: 20px;
border-collapse: collapse;
width: 100px;
}
/* Attach File Interface */
#st-attachments-attachinterface {
font-family: Helvetica, sans-serif;
font-size: 90%;
display: none;
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 2000;
background-image: url('../../images/st/popup/bg.png');
}
#st-attachments-manageinterface {
font-family: Helvetica, sans-serif;
font-size: 90%;
display: none;
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 2000;
background-image: url('../../images/st/popup/bg.png');
}
* html #st-attachments-attachinterface {
background-image: none;
}
* html #st-attachments-manageinterface {
background-image: none;
}
* html .popup-overlay {
background-image: url('../../images/st/popup/bg.png');
background-color: #000;
opacity: .70;
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 2001;
}
#st-attachments-attach-interface {
z-index: 2002;
background-color: #fff;
color: #000;
border: 4px solid #ccc;
padding: 1em;
width: 520px;
margin-left: auto;
margin-right: auto;
margin-top: 10%;
position: absolute;
top: 0px;
}
* html #st-attachments-attach-interface {
}
#st-attachments-attach-formtarget {
width: 0px;
height: 0px;
border: 0;
padding: 0;
margin: 0;
}
#st-attachments-attach-message {
font-size: 90%;
font-family: Verdana, Arial, Helvetica, Sans-Serif;
}
#st-attachments-attach-title {
font-weight: bold;
font-size: 120%;
}
#st-attachments-attach-close {
float: right;
margin-top: 6px;
}
#st-attachments-attach-uploadbutton {
float: right;
margin-right: 6px;
margin-top: 6px;
padding-bottom: 0;
}
#st-attachments-attach-fileprompt {
margin: 0.2em 0 0.4em 0;
padding-bottom: 0px;
}
#st-attachments-attach-submit {
font-size: 90%;
font-weight: bold;
}
#st-attachments-attach-filename {
font-size: 90%;
}
#st-attachments-attach-uploadmessage {
font-weight: bold;
margin-bottom: 1em;
display: none;
}
#st-attachments-attach-error {
font-weight: bold;
color: #f00;
margin-bottom: 1em;
display: none;
}
#st-attachments-attach-list {
display: none;
color: #666;
font-size: 90%;
margin-top: 1em;
margin-bottom: 1em;
border-top: 1px solid #4949BA;
border-bottom: 1px solid #4949BA;
background-color: #F5F5F5;
padding: 3px;
}
.st-attachments-attach-listlabel {
font-size: 90%;
color: #4949BA;
}
/* Queue File Dialog */
#st-attachmentsqueue-interface {
font-family: Helvetica, sans-serif;
font-size: 90%;
display: none;
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background-image: url('../../images/st/popup/bg.png'); /* Don't forget IE hack for ship! */
z-index: 2000;
}
* html #st-attachmentsqueue-interface {
background-image: none;
}
#st-attachmentsqueue-dialog {
z-index: 2002;
background-color: #fff;
color: #000;
border: 4px solid #ccc;
padding: 1em;
width: 530px;
margin-left: auto;
margin-right: auto;
margin-top: 10%;
position: absolute;
top: 0px;
}
* html #st-attachmentsqueue-dialog {
}
#st-attachmentsqueue-fileprompt {
margin-bottom: 0.4em;
margin-top: 0;
padding-bottom: 0;
}
#st-attachmentsqueue-title {
font-weight: bold;
font-size: 120%;
}
#st-attachmentsqueue-close {
float: right;
margin-top: 6px;
}
#st-attachmentsqueue-uploadbutton {
float: right;
margin-right: 6px;
margin-top: 6px;
padding-bottom: 0;
}
#st-attachmentsqueue-submit {
font-size: 90%;
}
#st-attachmentsqueue-filename {
font-size: 90%;
}
#st-attachmentsqueue-message {
font-size: 90%;
font-family: Verdana, Arial, Helvetica, Sans-Serif;
}
#st-attachmentsqueue-uploadmessage {
font-weight: bold;
margin-bottom: 1em;
display: none;
}
#st-attachmentsqueue-error {
font-weight: bold;
color: #f00;
margin-bottom: 1em;
display: none;
}
#st-attachmentsqueue-list {
display: none;
color: #666;
font-size: 90%;
margin-top: 1em;
margin-bottom: 1em;
border-top: 1px solid #4949BA;
border-bottom: 1px solid #4949BA;
background-color: #F5F5F5;
padding: 3px;
}
.st-attachmentsqueue-listlabel {
font-size: 90%;
color: #4949BA;
}
/* Lists */
tr.st-trbg-even, tr.st-trbg-even td{
background-color: #f3f7f7;
}
tr.w-st-even-row, tr.w-st-even-row td {
background-color: #f3f7f7;
}
.query-results-header-title, .query-results-header-last-edit-by {
text-align: left;
}
.query-results-row-revisions {
text-align: right;
}
.query-results-content {
font-size: 85%;
border-collapse: collapse;
border: 1px dashed #ddd;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}
.query-results-row {
border-collapse: collapse;
border: 1px dashed #ddd;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}
.query-results-row a {
text-decoration: underline;
color: #00f;
}
.query-results-row td {
font-family: Verdana;
padding: 0.3em;
border-left: 1px dashed #ddd;
border-right: 1px dashed #ddd;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
.query-results-header-row {
border-collapse: collapse;
border: 1px dashed #ddd;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}
.query-results-header-row a {
text-decoration: underline;
color: #00f;
}
.query-results-header-row th {
font-family: Helvetica;
padding: 0.3em;
border-left: 1px dashed #ddd;
border-right: 1px dashed #ddd;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
div.st-actionbutton {
float: left;
}
div#deleteme-st-actions-bar {
clear: both;
margin: 0.8em 20px 0.2em auto;
padding: 0;
}
/* Manage File Interface */
#st-attachments-manage-interface {
z-index: 2002;
background-color: #fff;
color: #000;
border: 4px solid #ccc;
padding: 1em;
width: 520px;
margin-left: auto;
margin-right: auto;
margin-top: 10%;
position: absolute;
top: 0px;
}
#st-attachments-manage-filetable {
height: 150px;
margin: 0;
padding: 0;
width: 100%;
overflow: auto;
border: 1px solid #ccc;
}
#st-attachments-manage-filelisting tbody td {
font-size: 90%;
}
#st-attachments-manage-filelisting {
width: 100%;
border-collapse: collapse;
border: 0;
margin: 0;
padding: 0;
}
#st-attachments-manage-fileheader {
background: #ccc;
font-weight: bold;
border-bottom: 1px black solid;
}
#st-attachments-manage-close {
float: right;
margin-top: 3px;
margin-right: -2px;
font-weight: bold;
}
#st-attachments-manage-delete {
margin-top: 3px;
float: left;
font-weight: bold;
}
.st-attachments-manage-filerow {
border-bottom: 1px solid #ccc;
}
.row-odd {
background-color: #eee;
}
.row-even {
background-color: #fff;
}
.row-on {
background-color: #009 !important;
color: white !important;
}
.row-on a {
color: #fff !important;
}
#st-attachments-manage-deletemessage {
color: red;
}
/* Page tools icons */
#st-pagetools-print {
background: url('../../images/st/pagetools/print.gif')
left center no-repeat;
}
#st-pagetools-email {
background: url('../../images/st/pagetools/email.gif')
left center no-repeat;
}
#st-pagetools-tools {
background: url('../../images/st/pagetools/tools.gif')
left center no-repeat;
}
/*
#st-pagetools-watch {
background: url('../../images/st/pagetools/watch-blue.gif')
left center no-repeat;
}
*/
/* *********** Settings *********** */
#st-settings-pane {
}
* html #settings-pane { font-size: 85%;}
.settings-start-table {
}
* html .settings-start-table { font-size: 90%;}
#st-settings-select {
padding: 0px 10px 10px 10px;
vertical-align: top;
width: 1px;
background-color: #eff1ec;
border: none;
}
#st-settings-section {
padding: 0px 10px 10px 10px;
vertical-align: top;
}
.settings-top-header {
margin-top: 1em;
font-weight: bold;
width: 15em;
}
.settings-header {
margin-top: 1em;
font-weight: bold;
}
.settings-selections {
padding: 0px 0px 0px 20px;
line-height: 1.5em;
}
.settings-selections a:visited, .settings-selections a:active {
color: #0000ff;
}
.settings-link {
clear: both;
display: block;
}
.settings-section-left {
text-align: right;
}
.settings-label {
font-weight: bold;
}
.settings-help {
color: #888;
}
.settings-comment {
}
.users-invite-message {
padding: 0.5em 0.5em 0.5em 2em;
background-color: #eee;
/* This seems necessary to fix an IE bug that sometimes
causes the text in this div to be invisible */
z-index: 1000;
}
.workspace-entry-header {
margin-top: .5em;
font-weight: bold;
}
.workspace-entry {
margin-left: 3em;
}
.workspace-entry-p {
margin-top: .5em;
margin-bottom: .75em;
}
.workspace-subentry {
font-style: italic;
font-weight: bold;
margin-left: 1.5em;
}
.preferences-td {
padding:.5em 0 1.5em 0;
}
.preferences-query {
text-align: left;
}
.preference-radio {
background-color: #cec;
}
.user-settings-listall-headings td {
background-color: #eff3ef;
}
#st-settings-save {
padding-bottom: 0.5em;
}
.standard-button-cancel {
font-weight: bold;
background-color: #71004b;
border-left: 1px solid #aaa;
border-top: 1px solid #aaa;
border-bottom: 2px solid #333;
border-right: 2px solid #333;
color: #f4f3b9;
width: 8em;
}
.standard-button-submit {
font-weight: bold;
background-color: #656084;
border-left: 1px solid #aaa;
border-top: 1px solid #aaa;
border-bottom: 2px solid #333;
border-right: 2px solid #333;
color: #f4f3b9;
width: 8em;
}
#st-settings {
font-family: Verdana, Arial, Helvetica, Sans-Serif;
font-size: 90%;
}
/* Listview Tabs */
#st-listview a:visited {
color: #551a8b;
}
#st-listview-tabs ul {
display: block;
list-style: none outside;
margin: 0 0 0 4em;
padding: 0;
font-family: Helvetica, Arial, Sans-serif;
font-size: 80%;
}
#st-listview-tabs li {
display: block;
float: left;
margin: 0 0.8em 0 0;
padding: 3px 0.6em 0 0.6em;
border: 1px solid #d8d8d8;
border-bottom: 1px solid rgb(128, 169, 243);
background-color: #f4f4f4;
position: relative;
bottom: -2px;
}
#st-listview-tabs li.spacer {
margin: 0 0.8em 0 2em;
}
#st-listview-tabs a {
color: #bbb;
text-decoration: none;
}
#st-listview-tabs li.selected {
background-color: #fff !important;
border: 1px solid rgb(128, 169, 243) !important;
border-bottom: 1px solid #fff !important;
font-weight: bold !important;
}
#st-listview-tabs li.selected a {
color: #000 !important;
}
/* Category List Display */
#st-category-display-links {
margin-bottom: 1em;
font-size: 90%;
}
#st-tag-listbody {
font-family: Helvetica, Verdana, sans-serif;
}
/* Attachments List Display */
#st-attachments-list-body table.button-table {
margin-top: 0.1em;
font-size: 80%;
}
/* ********** PageTools Menu ************** */
div#st-editing-tools {
float: left;
}
div#st-pagetools {
z-index: 300;
font-family: Helvetica, Verdana, sans-serif;
font-size: 10px;
float: right;
margin: 18px 0 0 0em;
color: #000;
vertical-align: bottom;
position: relative;
}
#st-pagetools a {
text-decoration: none;
color: black;
padding-left: 17px;
}
#st-pagetools span {
color: inherit;
padding-left: 17px;
vertical-align: top;
}
#st-pagetools span.st-watchlist-link {
color: inherit;
vertical-align: top;
}
.st-watchlist-link {
cursor: pointer;
}
div#st-pagetools ul.level2 {
z-index: 300;
margin: 0;
padding: 0;
background: white;
border: 1px solid #CCC;
border-width: 0 1px;
}
div#st-pagetools li {
position: relative;
list-style: none;
margin: 0;
float: left;
width: 7em;
line-height: 11px;
}
div#st-pagetools ul ul li:hover {
background: #BFE2FF;
}
div#st-pagetools li a {
display: block;
text-decoration: none;
}
div#st-pagetools>ul a {
width: auto;
}
div#st-pagetools ul ul {
position: absolute;
width: auto;
display: none;
}
div#st-pagetools ul ul li {
line-height: 1.5em;
/* width: 100%; */
width: 14em;
}
.first {
border-top: 1px solid #CCC;
}
.separator {
border-bottom: 1px solid #CCC;
}
div#st-pagetools ul ul li a {
border-bottom: 1px solid #CCC;
padding-left: 15px;
padding-right: 3px;
margin-right: 3px;
border: 0px;
}
div#st-pagetools li.submenu li.submenu:hover {
z-index: 300;
background-color: #BFE2FF;
}
div#st-pagetools ul.level1 li.submenu:hover ul.level2 {
display:block;
}
div#st-pagetools ul.level2 {
top: 1.0em;
left: -9.5em;
}
/*
=head2 Revision List Display
Change these styles to update the page revision list.
*/
#st-revision-list-table {
border-collapse: collapse;
font-size: 85%;
color: #000;
}
.st-page-title-decorator {
color: #C80000;
}
.st-revision-header-emphasis {
color: #C80000;
}
.st-revision-list-compare-button-row {
}
.st-revision-list-compare-button-cell {
padding-top: 0.3em;
text-align: center;
}
.st-revision-list-compare-button {
}
#st-revision-list-header-row {
}
#st-revision-list-header-select {
padding: 6px 2px 2px 2px;
text-align: center;
}
#st-revision-list-header-revision {
padding: 6px 2px 2px 2px;
text-align: left;
}
#st-revision-list-header-edited-by {
padding: 6px 2px 2px 2px;
text-align: center;
}
#st-revision-list-header-date {
padding: 6px 2px 2px 2px;
text-align: center;
}
.st-revision-list-row {
border-collapse: collapse;
border: 1px dashed #ddd;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}
.st-revision-list-row td {
font-family: Verdana;
padding: 0.3em;
border-left: 1px dashed #ddd;
border-right: 1px dashed #ddd;
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
.st-revision-list-row-select {
padding: 3px 0 2px 0;
text-align: center;
}
.st-revision-list-row-select-old {
}
.st-revision-list-row-select-new {
}
.st-revision-list-row-revision {
}
.st-revision-list-row-revision-link {
}
.st-revision-list-row-edited-by {
}
.st-revision-list-row-date {
}
/* Revision Menu */
#st-pagetools.st-revision-view-bar {
float: left;
}
ul.st-revision-menu {
list-style: none;
margin: 0;
padding: 0.2em;
font-size: 80%;
}
ul.st-revision-menu li {
float: left;
padding: 0 0.4em 0 0.4em;
border-right: thin solid #000000;
}
ul.st-revision-menu li.st-last {
border-right: none;
}
#st-restore-revision-button {
font-size: 80%;
}
/*
=head2 Revision Compare Display
When comparing two revisions of a page, these styles apply.
*/
#st-revision-compare-table {
background-color: #f0f0f0;
}
#st-revision-compare-table td {
background-color: white;
}
.st-revision-compare-old {
background-color: #fdd;
text-decoration: line-through;
}
.st-revision-compare-new {
background-color: #dfd;
font-weight: bold;
}
/* Weblog View */
#st-weblog {
padding: 0;
}
#st-content-weblog-display-width-controller {
}
#st-content-weblog-display-width-controller-nav {
width: 230px;
margin-left: 15px;
border-left: 5px solid #ddd;
margin-top: -1px;
}
#st-weblog-content {
font-family: Verdana, Helvetica, sans-serif;
margin-top: -1px;
margin-bottom: -1px;
border-top: 1px solid #80a9f3;
border-bottom: 1px solid #80a9f3;
}
#st-weblog-title {
font-family: 'Trebuchet MS', Verdana, Helvetica, sans-serif;
font-family: 'Times New Roman', serif;
background-color: #80a9f3;
color: #fff;
font-size: 150%;
font-weight: bold;
padding: 0.2em;
padding-left: 1em;
}
#st-weblog-wikititle {
font-family: Helvetica, Verdana, sans-serif;
font-style: italic;
font-size: 40%;
color: #fff;
margin-bottom: 0.2em;
margin-top: 0.1em;
padding-top: 0;
}
#st-weblog-titletext {
font-family: Helvetica, Verdana, sans-serif;
font-weight: bold;
color: #fff;
}
div.st-weblog-entry {
margin-top: 0.2em;
margin-bottom: 4.8em;
padding: 0 1.5em 0 1.5em;
}
.st-page-title {
clear: both;
}
div.st-weblog-entrytitle span.text {
font-family: Helvetica, Verdana, sans-serif;
font-size: 150%;
font-weight: bold;
color: #000;
}
.st-weblog-entrycontent {
font-family: Verdana, Helvetica, sans-serif;
font-size: 90%;
border-bottom: 1px solid #888;
}
.st-weblog-byline {
float: left;
text-align: left;
font-style: italic;
font-size: 70%;
font-family: Verdana, Helvetica, sans-serif;
}
.st-weblog-post-links {
float: right;
text-align: right;
font-size: 70%;
font-family: Verdana, Helvetica, sans-serif;
}
#st-weblog-archives, #st-weblog-navigation {
position: relative;
float: right;
width: 230px;
}
#st-weblog-archives {
margin-top: 15px;
clear: right;
}
#st-weblog-archives-title, #st-weblog-navigation-title {
margin-left: 15px;
font-family: Helvetica, sans-serif;
font-size: 95%;
font-weight: bold;
color: #999;
border-bottom: 2px solid #f99;
padding-bottom: 5px;
padding-top: 5px;
margin-bottom: 5px;
}
#st-weblog-navigation-content {
margin-left: 15px;
font-size: 80%;
}
#st-weblog-archives ul {
margin: 0;
padding: 0;
}
#st-weblog-archives ul li {
/* list-type: none; */
display: block;
font-size: 80%;
font-family: Helvetica, sans-serif;
padding-left: 15px;
}
#st-weblog-newpost {
padding: 0.5em 0.7em 0.3em 0.3em;
}
#st-weblog-newpost-button {
}
#st-weblog-actionbar-chooseweblog {
float: right;
}
#st-weblog-postbyemail {
font-size: 70%;
font-family: Verdana, Helvetica, sans-serif;
color: #def;
padding-top: 0.4em;
}
#st-weblog-postbyemail-link {
color: #00c;
}
.st-weblog-chooseprompt {
font-size: 90%;
font-family: Verdana, Helvetica, sans-serif;
padding-right: 0.2em;
color: #000;
}
.st-spacer {
padding-right: 0.1em;
padding-left: 0.1em;
}
.st-weblog-preventries {
padding-bottom: 20px;
clear: both;
}
.st-weblog-nextentries {
clear: both;
}
div.st-weblog-entrynav {
margin-top: 0.2em;
margin-bottom: 1.8em;
padding: 0;
}
span.st-weblog-previousentries, span.st-weblog-nextentries {
font-size: 90%;
font-family: Verdana, Helvetica, sans-serif;
padding-left: 1em;
}
/* ******* Page Stats ******** */
#st-usagereport-navbar {
font-size: 80%;
padding: 0;
margin: 0;
}
#st-usagereport-date {
font-weight: bold;
margin-top: 1em;
}
#st-page-usagereport h1 {
font-size: 1.3em;
font-weight: bold;
margin-top: 1.2em;
margin-bottom: 0.3em;
}
#st-page-usagereport h2 {
font-size: 1.1em;
font-weight: bold;
margin-top: 0.8em;
margin-bottom: 0.3em;
}
/* New Page */
#st-newpage-save, #st-newpage-duplicate {
display: none;
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: url('../../images/st/popup/bg.png'); /* Don't forget IE hack for ship! */
z-index: 2000;
}
#st-newpage-save-interface {
background-color: #fff;
color: #000;
border: 4px solid #ccc;
padding: 0.5em;
width: 450px;
margin-left: auto;
margin-right: auto;
margin-top: 10%;
position:absolute;
top:0px;
z-index:2003;
}
#st-newpage-duplicate-interface {
background-color: #fff;
color: #000;
border: 4px solid #ccc;
padding: 0.5em;
width: 530px;
margin-left: auto;
margin-right: auto;
margin-top: 10%;
position:absolute;
top:0px;
z-index:2003;
}
#st-newpage-save-title, #st-newpage-duplicate-title {
margin: 0;
padding: 0;
font-weight: bold;
font-family: Helvetica, sans-serif;
font-size: 100%;
}
#st-newpage-save-prompt, #st-newpage-duplicate-prompt {
font-family: Helvetica, sans-serif;
font-size: 90%;
margin-bottom: 0.4em;
}
#st-newpage-save-buttons, #st-newpage-duplicate-buttons {
margin-top: 0.8em;
text-align: right;
}
.st-newpage-duplicate-option {
font-family: Helvetica, sans-serif;
font-size: 90%;
margin: 0;
padding: 0;
}
#st-newpage-duplicate-pagename {
font-size: 90%;
}
.st-newpage-duplicate-emphasis {
background-color: #FFFF00;
font-weight: bold;
}
#st-newpage-save-field-pagename {
margin-bottom: 0;
margin-top: 0.2em;
padding-bottom: 0;
font-size: 90%;
}
#st-newpage-save-tip {
margin-bottom: 0;
margin-top: 1.2em;
padding-bottom: 0;
font-size: 75%;
color: #888;
}
/* Wikitext Styling */
.wiki {
}
.wiki hr {
margin-top: .4em;
margin-bottom: .4em;
}
.wiki .short-rule {
width: 25%;
}
.wiki .medium-rule {
width: 50%
}
.wiki ul,
.wiki ol,
.wiki blockquote {
margin-left: 2em;
padding-left: 0em;
}
.wiki table {
border-collapse: collapse;
}
.wiki td {
border: 1px;
border-style: solid;
padding: .2em;
vertical-align: top;
}
.wiki h1,
.wiki h2,
.wiki h3,
.wiki h4,
.wiki h5,
.wiki h6 {
font-weight: bold;
font-style: normal;
margin-top: 0.1em;
margin-bottom: 8px;
}
.wiki h1 {font-size: 200%;}
.wiki h2 {font-size: 170%;}
.wiki h3 {font-size: 145%;}
.wiki h4 {font-size: 125%;}
.wiki h5 {font-size: 110%;}
.wiki h6 {font-size: 100%;}
.wiki pre {
background-color: #eee; /* XXX */
margin-left: 1em;
margin-right: 1em;
padding: .2em;
}
.wiki .incipient {
text-decoration: none;
border-bottom: 1px dashed;
}
.wiki-include-title {
background-color: #ccccff;
}
.wiki .wiki {
position: relative;
background-color: #ddddff;
border: 1px solid #ccccff;
padding: 3px;
}
.wafl_existence_error {
color: rgb(200,0,0);
border-bottom: 0.2em dashed rgb(200,0,0);
}
#st-edit-mode-container {
}
#st-edit-mode-view {
}
#st-page-editing-uploadbutton {
z-index: 1500;
float: left;
}
/* Comment UI */
body#st-commentui {
background: #ffffff;
}
#st-commentui-container {
}
#st-commentui-container a:visited,
#st-commentui-container a:active {
color: #00f;
}
#st-commentui-notetop {
}
#st-commentui-controls {
}
#st-commentui-savelink {
background-color: #fffebd;
}
#st-commentui-cancellink {
}
#st-commentui-customfield {
}
#st-commentui-customfield .customfield-label {
}
#st-commentui-customfield .customfield-input {
}
#st-commentui-textarea {
padding: 0;
border-style: inset;
border-width: thin;
background-color: #ffd;
color: black;
width: 99%;
height: 150px;
}
/*
=head2 Send Page by Email
Styles for the 'Send Page by Email' popup, accessed from the 'Email' dropdown
menu on the page bar.
*/
#email-page {
background: #ffffff;
font-size: 80%;
}
.email-page-row {
clear: both;
}
.email-page-row-label {
font-weight: bold;
float: left;
width: 5em;
margin-left: 1.2em;
margin-right: 1.2em;
text-align: right;
}
.email-page-row-content {
float: left;
padding-bottom: 1.2em;
}
.email-page-user-select-column {
float: left;
padding-right: 1.2em;
width: 14em;
}
#email-page-user-select-column-center {
width: 10em;
}
.email-page-user-select-label {
text-align: center;
}
#email-page-user-select-add-label {
padding-top: 1em;
}
.email-page-user-select-button-group {
padding-bottom: 2em;
}
.email-page-input {
width: 120px;
clear: both;
display: block;
}
.email-page-select {
width: 175px;
font-size: x-small;
}
#email-page-error-message {
text-align: center;
}
#email-page-buttons-container {
clear: both;
}
#email-page-buttons {
text-align: center;
}
.email-page-input-new {
width: 175px;
}
/* System Status, Red with icon */
#st-system-status-alert {
clear: both;
width: 50%;
margin-left: 25%;
margin-top: 10px;
padding: 5px;
color: #c00;
font-weight: bold;
font-size: 80%;
background: transparent url('../../images/st/system-message/important-note.gif') no-repeat 5px center;
padding-left: 60px;
min-height: 38px;
}
* html #st-system-status-alert {
height: 38px;
}
/* System Status, Green */
#st-system-status {
clear: both;
text-align:center;
width: 80%;
margin-left: 10%;
padding: 8px 0 3px 0;
color: #0a0;
font-family: Arial, Helvetica, sans-serif;
font-size: 80%;
}
.socialtextLogo {
text-align: center;
}
/*}}}*/
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};
//--
//-- Sparklines
//--
config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
var data = [];
var min = 0;
var max = 0;
var v;
for(var t=0; t<params.length; t++) {
v = parseInt(params[t]);
if(v < min)
min = v;
if(v > max)
max = v;
data.push(v);
}
if(data.length < 1)
return;
var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
box.title = data.join(",");
var w = box.offsetWidth;
var h = box.offsetHeight;
box.style.paddingRight = (data.length * 2 - w) + "px";
box.style.position = "relative";
for(var d=0; d<data.length; d++) {
var tick = document.createElement("img");
tick.border = 0;
tick.className = "sparktick";
tick.style.position = "absolute";
tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
tick.style.left = d*2 + "px";
tick.style.width = "2px";
v = Math.floor(((data[d] - min)/(max-min)) * h);
tick.style.top = (h-v) + "px";
tick.style.height = v + "px";
box.appendChild(tick);
}
};
}
//}}}
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};
//--
//-- Crypto functions and associated conversion routines
//--
// Crypto "namespace"
function Crypto() {}
// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
var be = Array();
var len = Math.floor(str.length/4);
var i, j;
for(i=0, j=0; i<len; i++, j+=4) {
be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
}
while (j<str.length) {
be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
j++;
}
return be;
};
// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
var str = "";
for(var i=0;i<be.length*32;i+=8)
str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
return str;
};
// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
var hex = "0123456789ABCDEF";
var str = "";
for(var i=0;i<be.length*4;i++)
str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
return str;
};
// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
return Crypto.be32sToHex(Crypto.sha1Str(str));
};
// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};
// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
// Add 32-bit integers, wrapping at 32 bits
add32 = function(a,b)
{
var lsw = (a&0xFFFF)+(b&0xFFFF);
var msw = (a>>16)+(b>>16)+(lsw>>16);
return (msw<<16)|(lsw&0xFFFF);
};
// Add five 32-bit integers, wrapping at 32 bits
add32x5 = function(a,b,c,d,e)
{
var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
return (msw<<16)|(lsw&0xFFFF);
};
// Bitwise rotate left a 32-bit integer by 1 bit
rol32 = function(n)
{
return (n>>>31)|(n<<1);
};
var len = blen*8;
// Append padding so length in bits is 448 mod 512
x[len>>5] |= 0x80 << (24-len%32);
// Append length
x[((len+64>>9)<<4)+15] = len;
var w = Array(80);
var k1 = 0x5A827999;
var k2 = 0x6ED9EBA1;
var k3 = 0x8F1BBCDC;
var k4 = 0xCA62C1D6;
var h0 = 0x67452301;
var h1 = 0xEFCDAB89;
var h2 = 0x98BADCFE;
var h3 = 0x10325476;
var h4 = 0xC3D2E1F0;
for(var i=0;i<x.length;i+=16) {
var j,t;
var a = h0;
var b = h1;
var c = h2;
var d = h3;
var e = h4;
for(j = 0;j<16;j++) {
w[j] = x[i+j];
t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=16;j<20;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=20;j<40;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=40;j<60;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
for(j=60;j<80;j++) {
w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
}
h0 = add32(h0,a);
h1 = add32(h1,b);
h2 = add32(h2,c);
h3 = add32(h3,d);
h4 = add32(h4,e);
}
return Array(h0,h1,h2,h3,h4);
};
}
//}}}
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};
//--
//-- Deprecated code
//--
// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};
// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
var lookaheadRegExp = new RegExp(this.lookahead,"mg");
lookaheadRegExp.lastIndex = w.matchStart;
var lookaheadMatch = lookaheadRegExp.exec(w.source);
if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
var text = lookaheadMatch[1];
if(config.browser.isIE)
text = text.replace(/\n/g,"\r");
createTiddlyElement(w.output,"pre",null,null,text);
w.nextMatch = lookaheadRegExp.lastIndex;
}
};
// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
createTiddlyElement(place,"br");
};
// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
var i = this.indexOf(item);
return i == -1 ? null : i;
};
// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
return store.getLoader().internalizeTiddler(store,this,title,divRef);
};
// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
return store.getSaver().externalizeTiddler(store,this);
};
// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
return store.allTiddlersAsHtml();
}
// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
refreshPageTemplate(title);
}
// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
story.displayTiddlers(srcElement,titles,template,animate);
}
// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
story.displayTiddler(srcElement,title,template,animate);
}
// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;
// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");
}
//}}}
This is the home page for Dobrica Pavlinušić's random unstructured stuff.
Welcome to my new unsorted stuff site. If you are here to "learn about rot13"<http://en.wikipedia.org/wiki/ROT13> this might not be the right place.
If you are, however looking latest and/or unsorted snippets which didn't made to "my homepage"<http://www.rot13.org/~dpavlin/> or "blog"<http://blog.rot13.org/> you might be on right place.
| {search: category: projects} | {search: category: howto} | {recent_changes: rot13} |
{fetchrss: http://blog.rot13.org/index.xml}
{toc: }
Very old capacitive touch for EeePC 701
^ usb
.pre
dpavlin@brokeee:~$ lsusb -t -v
/: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
ID 1d6b:0001 Linux Foundation 1.1 root hub
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
ID 1d6b:0001 Linux Foundation 1.1 root hub
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
ID 1d6b:0001 Linux Foundation 1.1 root hub
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
ID 1d6b:0001 Linux Foundation 1.1 root hub
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/8p, 480M
ID 1d6b:0002 Linux Foundation 2.0 root hub
|__ Port 5: Dev 2, If 0, Class=Mass Storage, Driver=usb-storage, 480M
ID 0cf2:6225 ENE Technology, Inc. SD card reader (UB6225)
|__ Port 8: Dev 3, If 0, Class=Hub, Driver=hub/4p, 480M
ID 05e3:0608 Genesys Logic, Inc. Hub
|__ Port 3: Dev 5, If 1, Class=Video, Driver=uvcvideo, 480M
ID eb1a:2761 eMPIA Technology, Inc. EeePC 701 integrated Webcam
|__ Port 3: Dev 5, If 0, Class=Video, Driver=uvcvideo, 480M
ID eb1a:2761 eMPIA Technology, Inc. EeePC 701 integrated Webcam
|__ Port 1: Dev 4, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M
ID 0eef:0001 D-WAV Scientific Co., Ltd eGalax TouchScreen
.pre
https://forum.odroid.com/viewtopic.php?t=15239#p127773
^ xorg error
.pre
[ 39.523] (II) event14 - eGalax Inc. Touch Touchscreen: is tagged by udev as: Tablet
[ 39.719] (EE) event14 - eGalax Inc. Touch Touchscreen: libinput bug: missing tablet capabilities: btn-stylus resolution. Ignoring this device.
[ 39.719] (II) event14 - eGalax Inc. Touch Touchscreen: device is a tablet
[ 39.720] (II) event14 - failed to create input device '/dev/input/event14'.
[ 39.720] (EE) libinput: eGalax Inc. Touch Touchscreen: Failed to create a device for /dev/input/event14
[ 39.720] (EE) PreInit returned 2 for "eGalax Inc. Touch Touchscreen"
.pre
fix from https://www.embedded-engineer.de/dokuwiki/doku.php?id=start:egalax_touchscreen
.pre
apt install xserver-xorg-input-evdev
dpavlin@brokeee:~$ cat /usr/lib/udev/hwdb.d/61-evdev-local.hwdb
evdev:name:eGalax Inc. Touch Touchscreen*
EVDEV_ABS_00=::300
EVDEV_ABS_01=::300
systemd-hwdb update
udevadm trigger /dev/input/eventXX
root@brokeee:/etc/X11/xorg.conf.d# apt install xserver-xorg-input-evdev
root@brokeee:/etc/X11/xorg.conf.d# cat evdev-touch.conf
Section "InputClass"
Identifier "eGalax Inc. Touch Touchscreen"
MatchUSBID "0eef:0001"
Driver "evdev"
# https://www.x.org/releases/X11R7.5/doc/man/man4/evdev.4.html
Option "InvertX" "true"
EndSection
.pre
On my touchscreen with touch flex exiting on bottom left, I have to swap X axis
^ calibration
.pre
dpavlin@brokeee:~$ xinput_calibrator --output-type xorg.conf.d
Warning: multiple calibratable devices found, calibrating last one (eGalax Inc. Touch Touchscreen)
use --device to select another one.
Calibrating EVDEV driver for "eGalax Inc. Touch Touchscreen" id=11
current calibration values (from XInput): min_x=0, max_x=2047 and min_y=0, max_y=2047
Doing dynamic recalibration:
Inverting X and/or Y axis...
Setting calibration data: 1997, 73, 120, 1835
--> Making the calibration permanent <--
copy the snippet below into '/etc/X11/xorg.conf.d/99-calibration.conf' (/usr/share/X11/xorg.conf.d/ in some distro's)
Section "InputClass"
Identifier "calibration"
MatchProduct "eGalax Inc. Touch Touchscreen"
Option "Calibration" "1997 73 120 1835"
Option "SwapAxes" "0"
EndSection
.pre
^ userspace driver for newer chip
https://github.com/twoerner/hdmi-usb-touch
.pre
dpavlin@brokeee:~/hdmi-usb-touch$ git remote -v
origin https://github.com/twoerner/hdmi-usb-touch (fetch)
origin https://github.com/twoerner/hdmi-usb-touch (push)
dpavlin@brokeee:~/hdmi-usb-touch$ autoreconf -i
dpavlin@brokeee:~/hdmi-usb-touch$ sudo apt install libudev-dev
dpavlin@brokeee:~/hdmi-usb-touch$ ./configure
.pre
{toc: }
https://github.com/raphaelbs/esp32-cam-ai-thinker/blob/master/docs/about-esp32-cam.md
^ connection, flashing
connected to pl2303 serial
| pl2303 | esp32cam |
| 3v3 | not connected |
| rxd | UnR |
| rxd | UOT |
| gnd | GND |
| 5v | 5V |
{image: ESP32-CAM-pinout-new.png}
To program the board, I userd jumper to jump GPIO0 with GND pin next to it.
https://github.com/raphaelbs/esp32-cam-ai-thinker/blob/master/docs/esp32cam-pin-notes.md
^^ spi
SDI = IO12
SDO = IO13
SCK = IO14
CS = IO15
^ improved example app
https://github.com/easytarget/esp32-cam-webserver
.pre
cp myconfig.sample.h myconfig.h
vi myconfig.h
dpavlin@nuc:/nuc/esp32/esp32-cam-webserver$ platformio run
dpavlin@nuc:/nuc/esp32/esp32-cam-webserver$ pio run -t upload --upload-port /dev/ttyUSB2
"/home/dpavlin/.platformio/penv/bin/python" "/home/dpavlin/.platformio/packages/tool-esptoolpy/esptool.py" \
--chip esp32 --port "/dev/ttyUSB3" --baud 460800 --before default_reset --after hard_reset \
write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect \
0x1000 /home/dpavlin/.platformio/packages/framework-arduinoespressif32/tools/sdk/bin/bootloader_dio_40m.bin \
0x8000 /nuc/esp32/esp32-cam-webserver/.pio/build/esp32cam/partitions.bin \
0xe000 /home/dpavlin/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin \
0x10000 .pio/build/esp32cam/firmware.bin
.pre
^ timelapse
* https://bitluni.net/esp32camtimelapse
* https://github.com/bitluni/ESP32CamTimeLapse
^ ocr on device
https://github.com/jomjol/AI-on-the-edge-device
https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation
Remove glue from lens (very hard, using sharp knife), and rotate lens by 45 degrees until
picture is sharp (I had to use pliers to do this).
.pre
dpavlin@nuc:/nuc/esp32/AI-on-the-edge-device$ vi sd-card/wlan.ini
dpavlin@nuc:/nuc/esp32/AI-on-the-edge-device/code$ pio run
dpavlin@nuc:/nuc/esp32/AI-on-the-edge-device/code$ pio run -v -t upload --upload-port /dev/ttyUSB3
"/home/dpavlin/.platformio/penv/bin/python" "/home/dpavlin/.platformio/packages/tool-esptoolpy/esptool.py" \
--chip esp32 --port "/dev/ttyUSB3" --baud 460800 --before default_reset --after hard_reset \
write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect \
0x1000 /nuc/esp32/AI-on-the-edge-device/code/.pio/build/esp32cam/bootloader.bin \
0x8000 /nuc/esp32/AI-on-the-edge-device/code/.pio/build/esp32cam/partitions.bin \
0xd000 /nuc/esp32/AI-on-the-edge-device/code/.pio/build/esp32cam/ota_data_initial.bin \
0x10000 .pio/build/esp32cam/firmware.bin
# original flashing instructions
esptool write_flash 0x01000 bootloader.bin 0x08000 partitions.bin 0x10000 firmware.bin
# download raw picture
wget 192.168.3.112/img_tmp/raw.jpg
.pre
----
^ old, obsolete problems
It seems that my module is usually known as AI thinker variant. It has terrible picture which starts with huge green bias.
It also doesn't work for me in resolutions below 1024x768 (in current esp32 example as of 2019-08-02).
Plugging it into external 5V power supply did not helped much.
----
To solve green tint, I just left esp32cam module plugged in whole day and night. I guess that image sensor got discharged during night, but next day picture was fine.
Problem with image resolution was fixed by updating to more recent version of ESP32 support for Arduino (as of 2020-04-20 it works fine)
^ [Home Assistant]
https://jamesachambers.com/cheap-esp32-cam-home-assistant-esphome-camera-guide/
.pre
esphome:
name: esp32cam
friendly_name: esp32cam
esp32:
board: esp32cam
framework:
type: arduino
# Enable logging
logger:
level: VERBOSE
tx_buffer_size: 256
# Enable Home Assistant API
api:
encryption:
key: "MsJJJiDv9FTjZ1w8dfoy3Z8cQWjGOsk0m4Wgge0B+8w="
services: # change camera parameters on-the-fly
- service: camera_set_param
variables:
name: string
value: int
then:
- lambda: |-
bool state_return = false;
if (("contrast" == name) && (value >= -2) && (value <= 2)) { id(espcam).set_contrast(value); state_return = true; }
if (("brightness" == name) && (value >= -2) && (value <= 2)) { id(espcam).set_brightness(value); state_return = true; }
if (("saturation" == name) && (value >= -2) && (value <= 2)) { id(espcam).set_saturation(value); state_return = true; }
if (("special_effect" == name) && (value >= 0U) && (value <= 6U)) { id(espcam).set_special_effect((esphome::esp32_camera::ESP32SpecialEffect)value); state_return = true; }
if (("aec_mode" == name) && (value >= 0U) && (value <= 1U)) { id(espcam).set_aec_mode((esphome::esp32_camera::ESP32GainControlMode)value); state_return = true; }
if (("aec2" == name) && (value >= 0U) && (value <= 1U)) { id(espcam).set_aec2(value); state_return = true; }
if (("ae_level" == name) && (value >= -2) && (value <= 2)) { id(espcam).set_ae_level(value); state_return = true; }
if (("aec_value" == name) && (value >= 0U) && (value <= 1200U)) { id(espcam).set_aec_value(value); state_return = true; }
if (("agc_mode" == name) && (value >= 0U) && (value <= 1U)) { id(espcam).set_agc_mode((esphome::esp32_camera::ESP32GainControlMode)value); state_return = true; }
if (("agc_value" == name) && (value >= 0U) && (value <= 30U)) { id(espcam).set_agc_value(value); state_return = true; }
if (("agc_gain_ceiling" == name) && (value >= 0U) && (value <= 6U)) { id(espcam).set_agc_gain_ceiling((esphome::esp32_camera::ESP32AgcGainCeiling)value); state_return = true; }
if (("wb_mode" == name) && (value >= 0U) && (value <= 4U)) { id(espcam).set_wb_mode((esphome::esp32_camera::ESP32WhiteBalanceMode)value); state_return = true; }
if (("test_pattern" == name) && (value >= 0U) && (value <= 1U)) { id(espcam).set_test_pattern(value); state_return = true; }
if (true == state_return) {
id(espcam).update_camera_parameters();
}
else {
ESP_LOGW("esp32_camera_set_param", "Error in name or data range");
}
ota:
password: "09e4b58a1d186b8b33d100548f33d796"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
power_save_mode: none
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Esp32Cam Fallback Hotspot"
password: "GTIKgjitx2Re"
captive_portal:
# Example configuration entry
esp32_camera:
id: espcam
name: esp-cam
external_clock:
pin: GPIO0
frequency: 20MHz
i2c_pins:
sda: GPIO26
scl: GPIO27
data_pins: [GPIO5, GPIO18, GPIO19, GPIO21, GPIO36, GPIO39, GPIO34, GPIO35]
vsync_pin: GPIO25
href_pin: GPIO23
pixel_clock_pin: GPIO22
power_down_pin: GPIO32
resolution: 800x600
jpeg_quality: 10 # max. 63
max_framerate: 1.0fps
idle_framerate: 0.2fps
vertical_flip: true
horizontal_mirror: false
brightness: 2 # -2 to 2
contrast: 1 # -2 to 2
special_effect: none
# exposure settings
aec_mode: auto
aec2: false
ae_level: 0
aec_value: 300
# gain settings
agc_mode: auto
agc_gain_ceiling: 2x
agc_value: 0
# white balance setting
wb_mode: auto
output:
# white LED
- platform: ledc
channel: 2
pin: GPIO4
id: espCamLED
# red status light
- platform: gpio
pin:
number: GPIO33
inverted: True
id: gpio_33
light:
- platform: monochromatic
output: espCamLED
name: esp-cam light
- platform: binary
output: gpio_33
name: esp-cam led
switch:
- platform: restart
name: esp-cam restart
binary_sensor:
- platform: status
name: esp-cam status
.pre
This page will try to document my long-living dream of having bluetooth software keyboard HID
serial port and other stuff
* https://wiki.archlinux.org/index.php/bluetooth
{toc}
^ xkbd-bthid : a software Bluetooth HID Keyboard
* http://mulliner.org/bluetooth/xkbdbthid.php
^^ My Changes
{fetchrss http://git.rot13.org/?p=xkbdbthid.git;a=rss}
---
^ serial SP
^^ modify systemd script
.pre
tab:~# sdptool browese local
Failed to connect to SDP server on FF:FF:FF:00:00:00: No such file or directory
tab:~# vi /etc/systemd/system/bluetooth.target.wants/bluetooth.service
#ExecStart=/usr/lib/bluetooth/bluetoothd
# make sdptool browse local work again!
ExecStart=/usr/lib/bluetooth/bluetoothd --compat
tab:~# systemctl daemon-reload
tab:~# systemctl restart bluetooth.service
.pre
^^ bring up device and make it discoverable
.pre
root@rpi2:~# hciconfig
hci0: Type: BR/EDR Bus: UART
BD Address: B8:27:EB:A3:88:32 ACL MTU: 1021:8 SCO MTU: 64:1
DOWN
RX bytes:9088 acl:39 sco:0 events:343 errors:0
TX bytes:8208 acl:44 sco:0 commands:265 errors:0
root@rpi2:~# hciconfig hci0 up
root@rpi2:~# hciconfig
hci0: Type: BR/EDR Bus: UART
BD Address: B8:27:EB:A3:88:32 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING PSCAN
RX bytes:9784 acl:39 sco:0 events:382 errors:0
TX bytes:8967 acl:44 sco:0 commands:304 errors:0
root@rpi2:~# hciconfig hci0 piscan
.pre
^^ serial server
.pre
root@nuc:~# sdptool browse local | grep SP
root@nuc:~# sdptool add --channel=3 SP
Serial Port service registered
root@nuc:~# mknod -m 666 /dev/rfcomm0 c 216 0
root@nuc:~# rfcomm watch /dev/rfcomm0 3 /sbin/agetty rfcomm0 115200 linux
Waiting for connection on channel 3
Connection from B8:27:EB:A3:88:32 to /dev/rfcomm0
Press CTRL-C for hangup
Disconnected
Waiting for connection on channel 3
.pre
^^ serial client
.pre
root@rpi2:~# sdptool browse local | grep SP
root@rpi2:~# hcitool scan
Scanning ...
E0:2A:82:90:2D:7B nuc
root@rpi2:~# sdptool add --channel=3 SP
Serial Port service registered
root@rpi2:~# rfcomm connect /dev/rfcomm0 E0:2A:82:90:2D:7B 3
Connected /dev/rfcomm0 to E0:2A:82:90:2D:7B on channel 3
Press CTRL-C for hangup
.pre
Yada, tada, bigtable in C/C++
^ Compilation
.pre
apt-get install libboost-dev cmake liblog4cpp5-dev g++ libexpat1-dev libattr1-dev libreadline5-dev
.pre
{toc: }
Various infrared links collected here
{tag_list: IR}
^ Ir Send
Updated for HVAC Mitsubishi & Panasonic IR
* https://github.com/r45635/HVAC-IR-Control
^ Tasmota IR
^^ Configure module
Generic
D4 GPIO2 - AM2301
D6 GPIO12 - IN - IRrecv
D7 GPIO13 - Switch1 - reed relay to gnd
D5 GPIO14 - OUT - IRsend
^^ Configure WIFI
AP1 SSID, AP1 password
hostname - ir
^^ Configure MQTT
Host: rpi2
Topic: ir
^^ Configure Logging
Telemetry period: 10
^^ Configure Other
Device Name: IR
Friendly Name 1: IR
^^ Console
SerialLog 3 - turn serial log output https://tasmota.github.io/docs/Commands/
^^ reed sensor
switch 2 gpio 13
https://tasmota.github.io/docs/Buttons-and-Switches/#switchmode-15
expose gpio 13 in homeassistant as lodja_vrata sensor, remove connection with relay
.pre
SwitchText2 lodja_vrata
Setoption114 1
SwitchMode2 15
.pre
^ ESP IR TR
https://templates.blakadder.com/ESP_IR_TR.html
.pre
{"NAME":"Tasmota IR-Gateway","GPIO":[0,0,0,0,1056,0,0,0,0,0,1088,0,0,0],"FLAG":0,"BASE":18}
.pre
GPIO04 IRsend
GPIO14 IRrecv
^^ AM2301 + IR
module pinout
{image: esp_ir_tr-pinout.jpg}
{image: esp_ir_tr-am2301-gpio15.jpg}
(it's on GPIO13, ignore picture name which is wrong)
addition AM2301 on GPIO13 - requires custom tasmota ir build with USE_DHT enabled for IR_FIRMWARE build
.pre
(venv) dpavlin@nuc:/nuc/esp8266/Tasmota$ git diff
diff --git a/tasmota/include/tasmota_configurations.h b/tasmota/include/tasmota_configurations.h
index 1260892a0..c64d1ac1e 100644
--- a/tasmota/include/tasmota_configurations.h
+++ b/tasmota/include/tasmota_configurations.h
@@ -503,7 +503,8 @@
#undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface
#undef USE_LOX_O2 // Disable support for LuminOx LOX O2 Sensor
-#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor
+// XXX FIXME dpavlin -- keep DHT11
+//#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor
#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI
#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI
#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8
.pre
template:
.pre
{"NAME":"Tasmota IR-Gateway","GPIO":[0,0,0,0,1056,0,0,0,0,0,1088,1216,0,0],"FLAG":0,"BASE":18}
.pre
^ pictures
^^ position of plastic clips to unclip after removing screws
{file: innobox-v80-case-clips-20210522_192312.jpg}
^^ top of board
{file: innobox-v80-top-20210522_192339.jpg}
^^ bottom of board
{file: innobox-v80-back-20210522_192256.jpg}
^ software version
Hardware version: 1.0
Active image: 2
Firmware image 1: 1.0.839
Firmware image 2: 1.1.966
Checksum of image 1: 34e4b3948d00a869d961283510a7eb08
Checksum of image 2: a6e08754c908c237d1539cb143611697
Firmware bootloader: 1.9
CRC of bootloader: a6e08754c908c237d1539cb143611697
^ serial
4 pins, pin 1 marked with triangle
1: TX
2: RX
3: GND
4: 3V3 (?)
^ serial output
(partial)
.pre
BGA IC
Xtal:1
DDR3 init.
DRAMC init done.
Calculate size.
DRAM size=128MB
Set new TRFC.
7512DRAMC V1.2.2 (0)
EN751221 at Fri Apr 16 11:48:25 CST 2021 version 1.9 free bootbase
Memory size 128MB
Set SPI Clock to 50 Mhz
spi_nand_probe: mfr_id=0xc8, dev_id=0x21
Using Flash ECC.
Detected SPI NAND Flash : _SPI_NAND_DEVICE_ID_F50L1G, Flash Size=0x8000000
bmt pool size: 81
BMT & BBT Init Success
>>>> [get_env_info] hw_id:InnboxV80_PW2
>>>> [set_gpio_define] g_hw_id:InnboxV80_PW2
Reset button GPIO is: 0
Press any key in 3 secs to enter boot command mode.
............................................................
Invalid Power GPIO, just return and don't turn on Power LED
NAND FLASH
>>>> CTC: boot_flag_addr: 53e0fff; flag: 1 version_addr:53e1000 version:1.9<FF><FF><FF><FF>
==> boot flag = 1
Decompress to 80002000 free_mem_ptr=80E00000 free_mem_ptr_end=807B0000
from slave
Uncompressing [LZMA] ... done.
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Initializing cgroup subsys cpuacct
Linux version 3.18.21 (iskratel@2d7d74f016e9) (gcc version 4.6.3 (Buildroot 2015.08.1) ) #3 SMP Fri Apr 16 11:32:58 CST 2021
ISPRAM0: PA=00770000,Size=00010000,enabled
Config7: 0x80080500
memsize:120MB
EcoNet EN751221 SOC prom init
bootconsole [early0] enabled
CPU0 revision is: 00019558 (MIPS 34Kc)
Determined physical RAM map:
memory: 077fe000 @ 00002000 (usable)
Wasting 64 bytes for tracking 2 unused pages
Zone ranges:
Normal [mem 0x00002000-0x077fffff]
Movable zone start for each node
Early memory node ranges
node 0: [mem 0x00002000-0x077fffff]
Initmem setup node 0 [mem 0x00002000-0x077fffff]
Detected 1 available secondary CPU(s)
Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
PERCPU: Embedded 9 pages/cpu @810f3000 s5664 r8192 d23008 u36864
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 30478
Kernel command line: es=1
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Writing ErrCtl register=0002e01a
Readback ErrCtl register=0002e01a
nmi base is 81124200
Memory: 110280K/122872K available (7640K kernel code, 1290K rwdata, 1624K rodata, 304K init, 551K bss, 12592K reserved)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
Hierarchical RCU implementation.
NR_IRQS:64
tc3162_time_init: Init bus timeout and watchdog
plat_set_irq_affinity: cpu 0
plat_set_irq_affinity: cpu 0 vpe_id 0
plat_set_irq_affinity: irq_vpe0 1 irq_vpe1 0, irq = 10
plat_set_irq_affinity: irq num 10
plat_set_irq_affinity: cpu 0
plat_set_irq_affinity: cpu 0 vpe_id 0
plat_set_irq_affinity: irq_vpe0 1 irq_vpe1 0, irq = 33
plat_set_irq_affinity: irq num 33
CPU frequency 900.00 MHz
plat_time_init: Entered, mips_timer_ack ptr is [80006dd4]
Using 200.000 MHz high precision timer.
r4k_clockevent_init: setup_irq OK, irq is [31]
console [ttyS0] enabled
console [ttyS0] enabled
bootconsole [early0] disabled
bootconsole [early0] disabled
Calibrating delay loop... 597.60 BogoMIPS (lpj=2988032)
pid_max: default: 32768 minimum: 301
.pre
^ boot loader
.pre
bldr> ?
? Print out help messages.
help Print out help messages.
go Booting the linux kernel.
decomp Decompress kernel image to ram.
memrl <addr> Read a word from addr.
memwl <addr> <value> Write a word to addr.
dump <addr> <len> Dump memory content.
jump <addr> Jump to addr.
flash <dst> <src> <len> <oob> Write to flash from src to dst(oob: write nand oob if 1).
imginfo Show images info.
spinand_rwtest Flash Test
bdstore <flash dst> <bin src> Do backdoor config store
bdshow Show backdoor config
bdswitch[1|0] Enable or disable backdoor function
ddrcalswitch[1|0] Enable or disable ddr calibration funciton
drambistswitch[0|1|2] disable or enable, and quick or normal test
xmdm <addr> <len> Xmodem receive to addr.
miir <phyaddr> <reg> Read ethernet phy reg.
miiw <phyaddr> <reg> <value> Write ethernet phy reg.
cpufreq <freq num> / <m> <n> Set CPU Freq <156~450>(freq has to be multiple of 6)
ipaddr <ip addr> Change modem's IP.
httpd Start Web Server
mtd
bldr> bdshow
back door config is not support NAND Flash
.pre
{toc}
* http://sparktronics.blogspot.de/2008/05/synaptics-t1004-based-touchpad-to-ps2.html
* http://www.plastibots.com/index.php/2011/03/23/dual-led-desk-light-controller-arduino/
^ chip pinout
.pre
9-scroll down~
8-scroll up~
7-left click~
6-right click~
5-
4-
3-clk
2-data
1-
o <- dot on chip
44444
45678
|||||
||
|+-GND
+5V
.pre
^ T1004 920-000191-03RevA
connector pinout
| 1 | 5V | T20, T22 |
| 2 | DATA ||
| 3 | CLK ||
| 4 | RIGHT CLICK | T4 |
| 5 | LEFT CLICK | T6 |
| 6 | GND | T11, T10 |
| 7 | SCROLL UP | T5 |
| 8 | SCROLL DOWN | |
^^ N32N LS-734
Additional U shaped board from Compaq laptop with buttons on it
JP4 - to synaptics touch pad
JP1 - to motherboard
| 1 | red | 5V |
| 2 | green | 5V |
| 3 | yellow | switch SW5 |
| 4 | blue | LED D1 |
| 5 | gray | GND |
| 6 | pink | DATA |
| 7 | cyan | CLK |
| 8 | purple | GND |
Connecting to PS2 port demo: https://youtu.be/78CuKT-gVV4
^ T1006 920-000489-01RevA
HP laptop
connector pinout
| 1 | 5V | T20, T22 (after R470) |
| 2 | DATA | T11 |
| 3 | CLK | T10 |
| 4 | GND | T23, T30 |
| 5 |||
| 6 || PIN4 |
| 7 |||
| 8 || PIN5 |
test points:
T20 - 5V - R470 - T22
T23, T30 - GND
T11 - data
T10 - clk
T7 - left
T6 - right
T4 - up
T5 - down
^ T1006 920-000565-01RevA
t61p, has flex cable for connector
JP1
| 1 | ||
| 2 | GND ||
| 3 | ||
| 4 | GND ||
| 5 | ||
| 6 | ||
| 7 | GND ||
| 8 | 5V | T22 - R470 - T20 - pin 44 |
| 9 |||
| 10 | CLK | T11, pin 3 |
| 11 | DATA | T10, pin 2 |
| 12 | GND ||
| 13 |||
Intel SSD died
.pre
smartctl 6.6 2017-11-05 r4594 [x86_64-linux-4.19.0-4-amd64] (local build)
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Device Model: INTEL SSDSA2BW160G3H
Serial Number: BAD_CTX 00000136
LU WWN Device Id: 5 001517 a6be8caac
Firmware Version: 4PC10365
User Capacity: 8,388,608 bytes [8.38 MB]
Sector Size: 512 bytes logical/physical
Rotation Rate: Solid State Device
Device is: Not in smartctl database [for details use: -P showall]
ATA Version is: ATA8-ACS T13/1699-D revision 4
SATA Version is: SATA 2.6, 3.0 Gb/s
Local Time is: Sat Apr 27 17:23:39 2019 CEST
SMART support is: Unavailable - device lacks SMART capability.
=== START OF ENABLE/DISABLE COMMANDS SECTION ===
SMART Enable failed: scsi error badly formed scsi parameters
A mandatory SMART command failed: exiting. To continue, add one or more '-T permissive' options.
dpavlin@x200:~$ sudo hdparm -i /dev/sdc
/dev/sdc:
Model=INTEL SSDSA2BW160G3H, FwRev=4PC10365, SerialNo=BAD_CTX 00000136
Config={ Fixed }
RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=0
BuffType=unknown, BuffSize=unknown, MaxMultSect=16, MultSect=1
CurCHS=16/16/63, CurSects=16128, LBA=yes, LBAsects=16384
IORDY=on/off, tPIO={min:120,w/IORDY:120}, tDMA={min:120,rec:120}
PIO modes: pio0 pio3 pio4
DMA modes: mdma0 mdma1 mdma2
UDMA modes: udma0 udma1 udma2 udma3 udma4 udma5 *udma6
AdvancedPM=no WriteCache=enabled
Drive conforms to: unknown: ATA/ATAPI-2,3,4,5,6,7
* signifies the current active mode
dpavlin@x200:~/intel-ssd$ sudo smartctl -a /dev/sdc > smartctl.1
dpavlin@x200:~/intel-ssd$ sudo hdparm -i /dev/sdc > hdparm-i.1
dpavlin@x200:~/intel-ssd$ sudo hdparm -I /dev/sdc > hdparm-I.1
.pre
Internet visdom is that it's corrupted translation table and that secure erase or firmware update might help.
^ secure erase
https://ata.wiki.kernel.org/index.php/ATA_Secure_Erase
.pre
dpavlin@x200:~/intel-ssd$ sudo hdparm -I /dev/sdc | grep frozen
not frozen
# ok
root@x200:/home/dpavlin/intel-ssd# hdparm --user-master u --security-set-pass Eins /dev/sdc
security_password: "Eins"
/dev/sdc:
Issuing SECURITY_SET_PASS command, password="Eins", user=user, mode=high
root@x200:/home/dpavlin/intel-ssd# hdparm -I /dev/sdc | grep -C 3 enabled
Security:
Master password revision code = 65534
supported
enabled
not locked
not frozen
not expired: security count
root@x200:/home/dpavlin/intel-ssd# time hdparm --user-master u --security-erase Eins /dev/sdc
security_password: "Eins"
/dev/sdc:
Issuing SECURITY_ERASE command, password="Eins", user=user
real 0m19.285s
user 0m0.001s
sys 0m0.004s
.pre
This I assume reseted traslation table on ssd. First invocation of smartctl complained that I have to use -s on to turn smart on, so I did.
And it seems to work. All smart counters are reset (beacuse smart was off after secure erase).
.pre
dpavlin@tab:~$ sudo smartctl -a /dev/sda | head -20
smartctl 6.6 2016-05-31 r4324 [x86_64-linux-4.9.0-8-amd64] (local build)
Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org
=== START OF INFORMATION SECTION ===
Device Model: INTEL SSDSA2BW160G3H
Serial Number: BTPR144501A5160DGN
LU WWN Device Id: 5 001517 a6be8caac
Firmware Version: 4PC10365
User Capacity: 160,041,885,696 bytes [160 GB]
Sector Size: 512 bytes logical/physical
Rotation Rate: Solid State Device
Device is: Not in smartctl database [for details use: -P showall]
ATA Version is: ATA8-ACS T13/1699-D revision 4
SATA Version is: SATA 2.6, 3.0 Gb/s
Local Time is: Tue Apr 30 21:48:39 2019 CEST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled
=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED
dpavlin@tab:~$ sudo hdparm -i /dev/sda
/dev/sda:
Model=INTEL SSDSA2BW160G3H, FwRev=4PC10365, SerialNo=BTPR144501A5160DGN
Config={ Fixed }
RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=0
BuffType=unknown, BuffSize=unknown, MaxMultSect=16, MultSect=1
CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=312581808
IORDY=on/off, tPIO={min:120,w/IORDY:120}, tDMA={min:120,rec:120}
PIO modes: pio0 pio3 pio4
DMA modes: mdma0 mdma1 mdma2
UDMA modes: udma0 udma1 udma2 udma3 udma4 udma5 *udma6
AdvancedPM=no WriteCache=enabled
Drive conforms to: unknown: ATA/ATAPI-2,3,4,5,6,7
* signifies the current active mode
dpavlin@tab:~$ sudo hdparm -tT /dev/sda
/dev/sda:
Timing cached reads: 9340 MB in 2.00 seconds = 4675.95 MB/sec
Timing buffered disk reads: 736 MB in 3.01 seconds = 244.74 MB/sec
.pre
^ firmware update
https://blog.cihar.com/archives/2012/07/13/intel-ssd-firmware-update-linux/
But modified for recent Debian kernels
https://downloadcenter.intel.com/download/28749/Intel-SSD-Firmware-Update-Tool?v=t
.pre
dpavlin@x200:~$ unzip FirmwareUpdateTool_v3_0_7.zip -d FirmwareUpdateTool_v3_0_7
dpavlin@x200:~/FirmwareUpdateTool_v3_0_7$ sudo apt install grub-imageboot
dpavlin@x200:~/FirmwareUpdateTool_v3_0_7$ cat /etc/default/grub-imageboot
# Where to find the iso/floppy images
IMAGES="/boot/images"
# You can override the boot options for iso/floppy images here
# see http://syslinux.zytor.com/wiki/index.php/MEMDISK for details
#IMAGEOPTS="rawimg"
#ISOOPTS="iso"
dpavlin@x200:~/FirmwareUpdateTool_v3_0_7$ . /etc/default/grub-imageboot ; sudo mkdir -v $IMAGES
mkdir: created directory '/boot/images'
dpavlin@x200:~/FirmwareUpdateTool_v3_0_7$ sudo cp -v issdfut_64_3.0.7.iso /boot/images/
'issdfut_64_3.0.7.iso' -> '/boot/images/issdfut_64_3.0.7.iso'
dpavlin@x200:~/FirmwareUpdateTool_v3_0_7$ sudo update-grub
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.19.0-4-amd64
Found initrd image: /boot/initrd.img-4.19.0-4-amd64
Found linux image: /boot/vmlinuz-4.19.0-2-amd64
Found initrd image: /boot/initrd.img-4.19.0-2-amd64
Found memdisk: /boot/memdisk
Found iso image: /boot/images/issdfut_64_3.0.7.iso
done
.pre
This doesn't boot on x200 dual-core for me.
MiniPCIe/PCI/LPC Combo-Debug Card
[Altera] MAX 3000A CPLD
EPM3064ATC100
^ JTAG
6 pin header left of LCD, pull-up/down checked by unimer
1 3V
2 TMS pull-up
3 TDI pull-up
4 GND
5 TDO pull-down?
6 TCK pull-up
^^ pull-up/down pins
pull-up: TDO TMS TDI
pull-down: TCK
^^ [urjtag]
.pre
pi@raspberrypi ~ $ sudo dpkg -i urjtag_0.10-gpio-1_armhf.deb
pi@raspberrypi ~ $ sudo jtag
jtag> cable gpio tms=8 tdi=10 tdo=9 tck=11
Initializing GPIO JTAG Chain
jtag> detect
IR length: 10
Chain length: 1
Device Id: 00010111000001100100000011011101 (0x170640DD)
Manufacturer: Altera (0x0DD)
Part(0): EPM3064A (0x7064)
Stepping: 1
Filename: /usr/local/share/urjtag/altera/epm3064a/epm3064a
jtag> print chain
No. Manufacturer Part Stepping Instruction Register
---------------------------------------------------------------------------------------------
* 0 Altera EPM3064A 1 BYPASS BYPASS
jtag> include /usr/local/share/urjtag/altera/epm3064a/t100
jtag> instruction SAMPLE/PRELOAD
jtag> shift ir
jtag> shift dr
jtag> get signal IO2
jtag> get signal IN88
.pre
{image: pir-pinout.jpg}
^ BISS001 module
BISS001 - Micro Power PIR Motion Detector IC
* Input voltage: 3-5 V
* Hi: 0.7*Vdd = 0.7 * 5 V = 3.5 V
* Lo: 0.3*Vdd = 0.3 * 5 V = 1.5 V
^ HC-SR501 module
Technical data of the HC-SR501 Motion and Sensor Modules:
.pre
Input voltage: 4.5 V - 20 V
Digital output when motion is detected: 3.3 V (high)
Digital output with no movement on the HC-SR501: 0 V (low)
Working temperature in the environment: -15 � C to 70 � C
Delay Time 0.5 to 200 seconds
Angle of coverage: 100 �
Reach 5m - 7m
Size of the HC-SR501 motion:
Sensor Lens diameter: 23mm
Length: 24.03mm
Width: 32.34mm
Height (with lens): 24.66mm
Center screw hole spacing: 28 mm
Screw hole diameter: 2mm (M2)
.pre
^ Collect pir data using Linux gpio and send it to mqtt
both pots are all the way to the left (if jumper is on the left toword edge of board) to make minimal timeout
{file: pir.sh}
^^ gpio-utils
gpio-utils exists on Raspberry Pi
.pre
#!/bin/sh -e
led=/sys/devices/platform/rpi_control_board/leds/d1/brightness
# pir sensor connceted to 5V, GPIO12, GND
sudo stdbuf -oL -eL gpio-event-mon -n gpiochip0 -o 12 -r -f | while read gpio event time dir edge ; do
case $dir in
rising)
echo -n "^"
echo 1 > $led
;;
falling)
echo -n "_"
echo 0 > $led
;;
*)
echo -n "?"
;;
esac
done
.pre
^^ gpiod
alternative version using gpiod package available on sunxi
.pre
#!/bin/sh -e
led=/sys/class/leds/orangepi:red:status/brightness
# pir sensor connceted to 5V, PA6, GND
sudo stdbuf -oL -eL gpiomon 0 6 | while read event dir edge time ; do
echo "# $dir"
case $dir in
RISING)
echo -n "^"
echo 1 > $led
;;
FALLING)
echo -n "_"
echo 0 > $led
;;
*)
echo -n "?"
;;
esac
done
.pre
From: Gélineau, Samuel - Montreal
Date: Thu, 1 Nov 2007 17:31:54 -0400
----
Hi,
Your svn2cvs testsuite failed on my machine, and I had to fix both the testsuite and the perl script. I assume it must have worked for you the last time you ran your testsuite, and I have no clue why. I`m using CVS 1.12.9.
.pre
> cd svn2cvs/src
.pre
Running ./test.sh, the first abnormal behaviour I notice is at svn commit 14, "remove everything":
.pre
...
+ svn rm $svnco/dir/*
D /dev/shm/test-svn-co/dir/bar
D /dev/shm/test-svn-co/dir/baz
D /dev/shm/test-svn-co/dir/keep
D /dev/shm/test-svn-co/dir/keep-dir
D /dev/shm/test-svn-co/dir/l1/bar
D /dev/shm/test-svn-co/dir/l1/baz
D /dev/shm/test-svn-co/dir/l1/l2/bar
D /dev/shm/test-svn-co/dir/l1/l2/baz
D /dev/shm/test-svn-co/dir/l1/l2/l3/bar
D /dev/shm/test-svn-co/dir/l1/l2/l3/baz
D /dev/shm/test-svn-co/dir/l1/l2/l3
D /dev/shm/test-svn-co/dir/l1/l2
D /dev/shm/test-svn-co/dir/l1
D /dev/shm/test-svn-co/dir/skip_add
D /dev/shm/test-svn-co/dir/with space
+ svn revert $svnco/dir/keep $svnco/dir/keep-dir/keep
Reverted '/dev/shm/test-svn-co/dir/keep'
Skipped '/dev/shm/test-svn-co/dir/keep-dir/keep'
+ svn commit -m 'remove everything' $svnco
Deleting /dev/shm/test-svn-co/dir/bar
Deleting /dev/shm/test-svn-co/dir/baz
Deleting /dev/shm/test-svn-co/dir/keep-dir
Deleting /dev/shm/test-svn-co/dir/l1
Deleting /dev/shm/test-svn-co/dir/skip_add
Deleting /dev/shm/test-svn-co/dir/with space
Committed revision 14.
...
.pre
The interesting lines are:
.pre
Skipped '/dev/shm/test-svn-co/dir/keep-dir/keep'
...
Deleting /dev/shm/test-svn-co/dir/keep-dir
.pre
It`s obvious from the "svn revert" line that you never intended keep-dir to be deleted, yet it does gets deleted. I`m using svn 1.3.1 (r19032).
This time, the fix is in the testsuite itself:
.pre
--- svn2cvs/src/test.sh 2007-11-01 19:41:19.000000000 +0000
+++ svn2cvs/src/test.sh 2007-11-01 19:49:37.000000000 +0000
@@ -145,7 +145,7 @@
test
svn rm $svn_co/dir/* || exit
-svn revert $svn_co/dir/keep $svn_co/dir/keep-dir/keep
+svn revert $svn_co/dir/keep $svn_co/dir/keep-dir{,/keep}
svn commit -m "remove everything" $svn_co || exit
test
.pre
The relevant commit in the new testsuite now runs as follows:
.pre
...
+ svn rm $svnco/dir/*
D /dev/shm/test-svn-co/dir/bar
D /dev/shm/test-svn-co/dir/baz
D /dev/shm/test-svn-co/dir/keep
D /dev/shm/test-svn-co/dir/keep-dir
D /dev/shm/test-svn-co/dir/l1/bar
D /dev/shm/test-svn-co/dir/l1/baz
D /dev/shm/test-svn-co/dir/l1/l2/bar
D /dev/shm/test-svn-co/dir/l1/l2/baz
D /dev/shm/test-svn-co/dir/l1/l2/l3/bar
D /dev/shm/test-svn-co/dir/l1/l2/l3/baz
D /dev/shm/test-svn-co/dir/l1/l2/l3
D /dev/shm/test-svn-co/dir/l1/l2
D /dev/shm/test-svn-co/dir/l1
D /dev/shm/test-svn-co/dir/skip_add
D /dev/shm/test-svn-co/dir/with space
+ svn revert $svnco/dir/keep $svnco/dir/keep-dir $svnco/dir/keep-dir/keep
Reverted '/dev/shm/test-svn-co/dir/keep'
Reverted '/dev/shm/test-svn-co/dir/keep-dir'
Skipped '/dev/shm/test-svn-co/dir/keep-dir/keep'
+ svn commit -m 'remove everything' $svnco
Deleting /dev/shm/test-svn-co/dir/bar
Deleting /dev/shm/test-svn-co/dir/baz
Deleting /dev/shm/test-svn-co/dir/l1
Deleting /dev/shm/test-svn-co/dir/skip_add
Deleting /dev/shm/test-svn-co/dir/with space
Committed revision 14.
...
.pre
This time, the "skip" is legitimate. The testsuite still fails, though:
.pre
...
+ diff -x '.svn*' -x CVS -urw $svnco/dir/ $cvsco/dir/
Only in /dev/shm/test-cvs-co//dir/: l1
Only in /dev/shm/test-cvs-co//dir/: with space
+ exit
.pre
It again failed at this problematic last commit, "remove everything":
.pre
...
Starting after revision 13
## svn export --force -q -r 14 file:///dev/shm/test-svn-rep//dir /tmp/checkoutGGpuy/dir
NOTICE: using /dir as directory for svn
-------------------------------------------------------------------------------
r 14| gelineaus | 2007-11-01T20:22:39.115442Z
remove everything
svn2cvs: D /dir/bar
#### remove file: bar at ./svn2cvs.pl line 402.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'bar'
cvs remove: scheduling `bar' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'bar'
/dev/shm/test-cvs-rep/dir/bar,v <-- bar
new revision: delete; previous revision: 1.1
svn2cvs: D /dir/with space
WARNING: with space is not present in CVS, skipping...
svn2cvs: D /dir/baz
#### remove file: baz at ./svn2cvs.pl line 402.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'baz'
cvs remove: scheduling `baz' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'baz'
/dev/shm/test-cvs-rep/dir/baz,v <-- baz
new revision: delete; previous revision: 1.1
svn2cvs: D /dir/l1
WARNING: l1 is not present in CVS, skipping...
svn2cvs: D /dir/skip_add
#### remove file: skip_add at ./svn2cvs.pl line 402.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'skip_add'
cvs remove: scheduling `skip_add' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'skip_add'
/dev/shm/test-cvs-rep/dir/skip_add,v <-- skip_add
new revision: delete; previous revision: 1.1
commit ignored, no files
subversion revision 14 commited to CVS
/dev/shm/test-cvs-rep/dir/.svnrev,v <-- .svnrev
new revision: 1.15; previous revision: 1.14
+ update_all
+ update_svn
+ svn update /dev/shm/test-svn-co/
At revision 14.
+ update_cvs
+ cd /dev/shm/test-cvs-co/
+ cvs -f update -d dir
cvs update: Updating dir
U dir/.svnrev
cvs update: `dir/bar' is no longer in the repository
cvs update: `dir/baz' is no longer in the repository
cvs update: `dir/skip_add' is no longer in the repository
cvs update: Updating dir/keep-dir
cvs update: Updating dir/l1
cvs update: Updating dir/l1/l2
cvs update: Updating dir/l1/l2/l3
cvs update: Updating dir/with space
+ cd-
+ diff -x '.svn*' -x CVS -urw /dev/shm/test-svn-co//dir/ /dev/shm/test-cvs-co//dir/
Only in /dev/shm/test-cvs-co//dir/: l1
Only in /dev/shm/test-cvs-co//dir/: with space
+ exit
.pre
The relevant lines are:
.pre
...
svn2cvs: D /dir/with space
WARNING: with space is not present in CVS, skipping...
...
svn2cvs: D /dir/l1
WARNING: l1 is not present in CVS, skipping...
...
Only in /dev/shm/test-cvs-co//dir/: l1
Only in /dev/shm/test-cvs-co//dir/: with space
+ exit
.pre
In other words, svn2cvs.pl cannot see directories and refuses to remove them. This is because of the in_entries() function, which does not consider lines describing directories. Here`s the fix:
.pre
--- svn2cvs/src/svn2cvs.pl 2007-11-01 20:21:22.000000000 +0000
+++ svn2cvs/src/svn2cvs.pl 2007-11-01 20:36:52.000000000 +0000
@@ -263,6 +263,7 @@ sub in_entries($) {
|| return 0; #die "no entries file: $dir/CVS/Entries";
while (<$fh>) {
return 1 if (m{^/$file/});
+ return 1 if (m{^D/$file/});
}
close($fh);
return 0;
.pre
But the problematic last commit _still_ fails:
.pre
Starting after revision 13
## svn export --force -q -r 14 file:///dev/shm/test-svn-rep//dir /tmp/checkout1jkCl/dir
NOTICE: using /dir as directory for svn
-------------------------------------------------------------------------------
r 14| gelineaus | 2007-11-01T20:53:32.113268Z
remove everything
svn2cvs: D /dir/bar
#### remove file: bar at ./svn2cvs.pl line 403.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'bar'
cvs remove: scheduling `bar' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'bar'
/dev/shm/test-cvs-rep/dir/bar,v <-- bar
new revision: delete; previous revision: 1.1
svn2cvs: D /dir/with space
#### remove directory: with space at ./svn2cvs.pl line 383.
#### entries(with space) => at ./svn2cvs.pl line 249.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'with space'
cvs remove: Removing with space
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'with space'
cvs commit: Examining with space
## cvs -f -d /dev/shm/test-cvs-rep/ update -dP .
cvs update: Updating .
cvs update: Updating keep-dir
cvs update: Updating l1
cvs update: Updating l1/l2
cvs update: Updating l1/l2/l3
cvs update: Updating with space
svn2cvs: D /dir/baz
#### remove file: baz at ./svn2cvs.pl line 403.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'baz'
cvs remove: scheduling `baz' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'baz'
/dev/shm/test-cvs-rep/dir/baz,v <-- baz
new revision: delete; previous revision: 1.1
svn2cvs: D /dir/l1
#### remove directory: l1 at ./svn2cvs.pl line 383.
#### entries recurse into: l1/l2 at ./svn2cvs.pl line 239, <$fh> line 3.
#### entries recurse into: l1/l2/l3 at ./svn2cvs.pl line 239, <> line 3.
#### entries(l1/l2/l3) => bar|baz at ./svn2cvs.pl line 249.
#### entries(l1/l2) => bar|baz|l3/bar|l3/baz|l3 at ./svn2cvs.pl line 249.
#### entries(l1) => bar|baz|l2/bar|l2/baz|l2/l3/bar|l2/l3/baz|l2/l3|l2 at ./svn2cvs.pl line 249.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/bar'
cvs remove: scheduling `l1/bar' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/bar'
/dev/shm/test-cvs-rep/dir/l1/bar,v <-- bar
new revision: delete; previous revision: 1.1
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/baz'
cvs remove: scheduling `l1/baz' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/baz'
/dev/shm/test-cvs-rep/dir/l1/baz,v <-- baz
new revision: delete; previous revision: 1.1
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/bar'
cvs remove: scheduling `l1/l2/bar' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/bar'
/dev/shm/test-cvs-rep/dir/l1/l2/bar,v <-- bar
new revision: delete; previous revision: 1.2
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/baz'
cvs remove: scheduling `l1/l2/baz' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/baz'
/dev/shm/test-cvs-rep/dir/l1/l2/baz,v <-- baz
new revision: delete; previous revision: 1.2
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/l3/bar'
cvs remove: scheduling `l1/l2/l3/bar' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/l3/bar'
/dev/shm/test-cvs-rep/dir/l1/l2/l3/bar,v <-- bar
new revision: delete; previous revision: 1.3
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/l3/baz'
cvs remove: scheduling `l1/l2/l3/baz' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/l3/baz'
/dev/shm/test-cvs-rep/dir/l1/l2/l3/baz,v <-- baz
new revision: delete; previous revision: 1.3
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/l3'
cvs remove: Removing l1/l2/l3
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/l3'
cvs commit: Examining l1/l2/l3
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2'
cvs remove: Removing l1/l2
cvs remove: Removing l1/l2/l3
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2'
cvs commit: Examining l1/l2
cvs commit: Examining l1/l2/l3
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1'
cvs remove: Removing l1
cvs remove: Removing l1/l2
cvs remove: Removing l1/l2/l3
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1'
cvs commit: Examining l1
cvs commit: Examining l1/l2
cvs commit: Examining l1/l2/l3
## cvs -f -d /dev/shm/test-cvs-rep/ update -dP .
cvs update: Updating .
cvs update: Updating keep-dir
cvs update: Updating l1
cvs update: Updating l1/l2
cvs update: Updating l1/l2/l3
cvs update: Updating with space
svn2cvs: D /dir/skip_add
#### remove file: skip_add at ./svn2cvs.pl line 403.
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'skip_add'
cvs remove: scheduling `skip_add' for removal
cvs remove: use `cvs commit' to remove this file permanently
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'skip_add'
/dev/shm/test-cvs-rep/dir/skip_add,v <-- skip_add
new revision: delete; previous revision: 1.1
commit ignored, no files
subversion revision 14 commited to CVS
/dev/shm/test-cvs-rep/dir/.svnrev,v <-- .svnrev
new revision: 1.15; previous revision: 1.14
+ update_all
+ update_svn
+ svn update /dev/shm/test-svn-co/
At revision 14.
+ update_cvs
+ cd /dev/shm/test-cvs-co/
+ cvs -f update -d dir
cvs update: Updating dir
U dir/.svnrev
cvs update: `dir/bar' is no longer in the repository
cvs update: `dir/baz' is no longer in the repository
cvs update: `dir/skip_add' is no longer in the repository
cvs update: Updating dir/keep-dir
cvs update: Updating dir/l1
cvs update: `dir/l1/bar' is no longer in the repository
cvs update: `dir/l1/baz' is no longer in the repository
cvs update: Updating dir/l1/l2
cvs update: `dir/l1/l2/bar' is no longer in the repository
cvs update: `dir/l1/l2/baz' is no longer in the repository
cvs update: Updating dir/l1/l2/l3
cvs update: `dir/l1/l2/l3/bar' is no longer in the repository
cvs update: `dir/l1/l2/l3/baz' is no longer in the repository
cvs update: Updating dir/with space
+ cd-
+ diff -x '.svn*' -x CVS -urw /dev/shm/test-svn-co//dir/ /dev/shm/test-cvs-co//dir/
Only in /dev/shm/test-cvs-co//dir/: l1
Only in /dev/shm/test-cvs-co//dir/: with space
+ exit
.pre
The relevant lines are:
.pre
...
svn2cvs: D /dir/with space
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'with space'
cvs remove: Removing with space
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'with space'
...
## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1'
cvs remove: Removing l1
cvs remove: Removing l1/l2
cvs remove: Removing l1/l2/l3
## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1'
...
Only in /dev/shm/test-cvs-co//dir/: l1
Only in /dev/shm/test-cvs-co//dir/: with space
+ exit
.pre
Thus cvs was asked to delete the directories, but didn`t. This is no surprise, since CVS was _designed_ not to remove directories. From the CVS manual:
> 7.3 Removing directories
> In concept, removing directories is somewhat similar to removing files--you want the directory to not exist in your current working directories, but you also want to be able to retrieve old releases in which the directory existed.
> The way that you remove a directory is to remove all the files in it. You don't remove the directory itself; there is no way to do that. Instead you specify the '-P' option to cvs update or cvs checkout, which will cause CVS to remove empty directories from working directories. (Note that cvs export always removes empty directories.) Probably the best way to do this is to always specify '-P'; if you want an empty directory then put a dummy file (for example '.keepme') in it to prevent '-P' from removing it.
> Note that '-P' is implied by the '-r' or '-D' options of checkout. This way, CVS will be able to correctly create the directory or not depending on whether the particular version you are checking out contains any files in that directory.
Thus the fix would be to automatically add a ".keepme" file upon directory creation, and to removed it (along with the other files in the directory) upon directory deletion. The testsuite also needs to be updated to use the "-P" flag. Thus, my last patch:
.pre
diff -r -uprN svn2cvs/src/svn2cvs.pl svn2cvs/src/svn2cvs.pl
--- svn2cvs/src/svn2cvs.pl 2007-11-01 20:36:52.000000000 +0000
+++ svn2cvs/src/svn2cvs.pl 2007-11-01 21:06:04.000000000 +0000
@@ -104,7 +104,8 @@ sub add_dir($$) {
next if in_entries($curr_dir);
next if ( -e "$curr_dir/CVS" );
+ log_system( "touch '$curr_dir/.keepme'", "creation of .keepme file (to keep $curr_dir alive in CVS) failed" );
- log_system( "$cvs add '$curr_dir'", "cvs add of $curr_dir failed" );
+ log_system( "$cvs add '$curr_dir' '$curr_dir/.keepme'", "cvs add of $curr_dir failed" );
}
}
diff -r -uprN svn2cvs/src/test.sh svn2cvs/src/test.sh
--- svn2cvs/src/test.sh 2007-11-01 20:36:32.000000000 +0000
+++ svn2cvs/src/test.sh 2007-11-01 21:06:39.000000000 +0000
@@ -52,13 +52,13 @@ cd- || exit
rm -Rf $cvs_co || exit
mkdir $cvs_co || exit
-cd $cvs_co && cvs -f co dir && cd- || exit
+cd $cvs_co && cvs -f co -P dir && cd- || exit
function svn2cvs() {
./svn2cvs.pl file://$svn_rep/dir $cvs_rep dir || exit
}
function update_cvs() {
- cd $cvs_co && cvs -f update -d dir && cd- || exit
+ cd $cvs_co && cvs -f update -P -d dir && cd- || exit
}
function update_svn() {
svn update $svn_co || exit
@@ -70,7 +70,7 @@ function update_all() {
function test() {
svn2cvs
update_all
- diff -x .svn\* -x CVS -urw $svn_co/dir/ $cvs_co/dir/ || exit
+ diff -x .svn\* -x CVS -x '\.keep' -urw $svn_co/dir/ $cvs_co/dir/ || exit
}
svn2cvs
.pre
And now the problematic test finally passes.
Hoping to be useful,
* Samuel Gélineau
----
This is one of best bug reports I ever received or actually read :-) It seems that "other projects also appriciate bug reports"<http://dev.eclipse.org/mhonarc/lists/aspectj-announce/msg00055.html> like:
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=96111
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=98320
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=98592
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=99168
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=99228
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=100227
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=100260
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=102212
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=102357
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=104024
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=105181
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=106630
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=106634
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=106874
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=107059
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=107858
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=107898
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=108014
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=104046
"Jifty"<http://jifty.org/> notes for installing production Jifty instance on Debian etch
{toc: }
^ /etc/apt/sources.list
.pre
deb http://debian.carnet.hr/debian etch main contrib non-free
deb http://security.debian.org/ etch/updates main contrib non-free
deb http://debian.jifty.org/debian etch jifty
.pre
^ packages
.pre
sudo apt-get install subversion make svk ssmtp jifty libmodule-install-perl
.pre
^ configuration
^^ SMTP
Edit `/etc/ssmtp/ssmtp.conf` to include valid `mailhub`
Apply patch "#24482"<http://rt.cpan.org/Public/Bug/Display.html?id=24482> to `Email::Send` to fix mail sending or execute fillowing command:
.pre
sudo ln -sf /usr/sbin/sendmail /usr/local/bin/
.pre
^ application
.pre
svk co svn+ssh://llin-svn/home/dpavlin/private/svn/Arh
cd Arh
perl Makefile.PL
# sudo is needed if you don't have all modules
sudo make
./bin/jifty schema
./bin/jifty server
.pre
CJMCU-811 CCS811 Carbon Monoxide CO VOCs Air Quality Digital Gas Sensor
https://revspace.nl/CJMCU-811
^ pins
VCC this is directly connected to the IC (there is no voltage regulator on board), connect this to 3.3V
GND to ground obviously
SCL signal from I2C
SDA signal from I2C
WAK this needs to be low (!) in order for the chip to be active
INT can be left unconnected
RST can be left unconnected
ADD can be left unconnected. It has a 10k pull-down to GND, setting the I2C address to 0x5A.
^ firmware upgrade
https://github.com/maarten-pennings/CCS811/tree/master/examples/ccs811flash
.pre
dpavlin@nuc:~/Arduino/libraries$ git clone https://github.com/maarten-pennings/CCS811
.pre
Wiring for ESP8266 NodeMCU boards: VDD to 3V3, GND to GND, SDA to D2, SCL to D1, nWAKE to D3 (or GND)
Serial output with sensor out of (china) bag:
.pre
setup: Starting CCS811 basic demo
setup: ccs811 lib version: 12
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 1100
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: eco2=0 ppm etvoc=0 ppb
CCS811: eco2=0 ppm etvoc=0 ppb
CCS811: eco2=0 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
.pre
^^ upgrade serial output
.pre
Starting CCS811 flasher
setup: library version: 12
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 1100
setup: comment-out this code line if you want to flash
loop: ended ...
loop: ended ...
loop: ended ...
loop: ended ...
loop: ended ...
loop: ended ...
loop: ended ...
loop: ended ...
ccs811: ping ok
ccs811: reset ok
ccs811: status (reset1) 10 ok
ccs811: app-erase ok
ccs811: status (app-erase) 40 ok
ccs811: writing 5120 ................................................................ 4608
ccs811: writing 4608 ................................................................ 4096
ccs811: writing 4096 ................................................................ 3584
ccs811: writing 3584 ................................................................ 3072
ccs811: writing 3072 ................................................................ 2560
ccs811: writing 2560 ................................................................ 2048
ccs811: writing 2048 ................................................................ 1536
ccs811: writing 1536 ................................................................ 1024
ccs811: writing 1024 ................................................................ 512
ccs811: writing 512 ................................................................ 0
ccs811: app-verify ok
ccs811: status (app-verify) 30 ok
ccs811: reset2 ok
ccs811: status (reset2) 10 ok
setup: Starting CCS811 basic demo
setup: ccs811 lib version: 12
setup: hardware version: 12
setup: bootloader version: 1000
setup: application version: 2000
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: waiting for (new) data
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=409 ppm etvoc=1 ppb
CCS811: eco2=414 ppm etvoc=2 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=407 ppm etvoc=1 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=408 ppm etvoc=1 ppb
CCS811: eco2=414 ppm etvoc=2 ppb
CCS811: eco2=417 ppm etvoc=2 ppb
CCS811: eco2=414 ppm etvoc=2 ppb
CCS811: eco2=408 ppm etvoc=1 ppb
CCS811: eco2=408 ppm etvoc=1 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
CCS811: eco2=406 ppm etvoc=0 ppb
CCS811: eco2=400 ppm etvoc=0 ppb
.pre
Since my sensor is new, I used firmware 2.0.0 to allow initial burn-in compensation.
^ temperature compensation
https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library/blob/master/examples/Example2_BME280Compensation/Example2_BME280Compensation.ino
^ esphome
.pre
esphome:
name: ccs811
friendly_name: ccs811
esp8266:
board: nodemcuv2
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX="
ota:
password: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Ccs811 Fallback Hotspot"
password: "XXXXXXXXXXXX"
captive_portal:
# Example configuration entry
i2c:
sda: D2
scl: D1
sensor:
- platform: ccs811
eco2:
name: "CCS811 eCO2 Value"
tvoc:
name: "CCS811 Total Volatile Organic Compound"
address: 0x5A
update_interval: 15s
- platform: bme280
temperature:
name: "BME280 Temperature"
id: bme280_temperature
pressure:
name: "BME280 Pressure"
id: bme280_pressure
humidity:
name: "BME280 Relative Humidity"
id: bme280_humidity
address: 0x76
update_interval: 15s
.pre
{toc}
^ Raspidancer
Facedancer on [RaspberryPi] http://wiki.yobi.be/wiki/Raspdancer
Newer software https://github.com/ktemkin/Facedancer
Schema: http://wiki.yobi.be/images/1/18/Raspdancer21_v10_sch.png
.pre
pi@picam ~ $ git clone https://github.com/ktemkin/Facedancer
pi@picam ~ $ git clone https://github.com/lthiery/SPI-Py
Cloning into 'SPI-Py'...
remote: Counting objects: 81, done.
remote: Total 81 (delta 0), reused 0 (delta 0), pack-reused 81
Unpacking objects: 100% (81/81), done.
Checking connectivity... done.
pi@picam ~ $ cd SPI-Py/
pi@picam ~/SPI-Py $ sudo apt-get install python3-dev
pi@picam ~/SPI-Py $ python3 setup.py build
pi@picam ~/SPI-Py $ sudo python3 setup.py install
pi@picam ~/Facedancer $ export BACKEND=raspdancer
pi@picam ~/Facedancer $ sudo -E ./facedancer-serial.py
pi@picam ~/Facedancer $ sudo -E ./facedancer-serial.py
Using MAXUSB backend.
MAXUSB initialized
MAXUSB enabled
MAXUSB revision 0
<facedancer.backends.RaspdancerMaxUSBApp.RaspdancerMaxUSBApp object at 0xb6a67710>
MAXUSB connected device USB Serial device
.pre
^ USB Host Shield for Arduino Pro Mini
http://shop.tkjelectronics.dk/product_info.php?cPath=22&products_id=45
Schema: http://www.tkjelectronics.dk/uploads/usbhost/UHS_mini_10.pdf
^^ problems
* VBCOMP is not routed on this board
* VBUS (usb VCC) is 3.3V not 5V
^ MAX3421 kernel module
* device tree support https://github.com/AlexanderAmelkin/linux-wandboard/commits/for-linux-usb
^^ Raspberry pi kernel modules
* https://github.com/notro/rpi-source/wiki/Examples-on-how-to-build-various-modules
.pre
pi@picam ~ $ sudo apt-get install libncurses5-dev
pi@picam ~ $ rpi-source
pi@picam ~/linux $ ./scripts/diffconfig
+USB_MAX3421_HCD m
pi@picam ~/linux $ grep MAX3421 .config
CONFIG_USB_MAX3421_HCD=m
pi@picam ~/linux $ make SUBDIRS=drivers/usb/host/ modules
.pre
^^ cross-compile
dpavlin@klin:/klin/rpi/linux$ cat run.sh
# https://www.raspberrypi.org/documentation/linux/kernel/building.md
.pre
#make oldconfig
KERNEL=kernel7
#make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig
#make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- oldconfig
make -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs
test -d mnt && rm -Rf mnt/
mkdir -p mnt/boot/overlays
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/ modules_install
cp arch/arm/boot/zImage mnt/boot/$KERNEL.img
cp arch/arm/boot/dts/*.dtb mnt/boot/
cp arch/arm/boot/dts/overlays/*.dtb* mnt/boot/overlays/
cp arch/arm/boot/dts/overlays/README mnt/boot/overlays/
.pre
^ links
* https://github.com/DavidBuchanan314/wifi-sdcf - this exact card, includes sd card emulator, but no client for real card
* https://habr.com/post/216039/ - something similar for transcend in russian
** https://github.com/kaist/shoot-and-view
^ info
WIFI Adapter Memory Card TF Micro-SD to CF Compact Flash Card Kit for Digit Y8X8
Insert your Micro-SD HC card into WiFi CF adapter and you can access high quality photos and videos sent wirelessly from your camera via Wi-Fi to your Smartphone or tablet to share.
Supports "with the beat-per-view" feature and both Apple Ios & Android devices
WiFi-CF settings: WiFi password,AP Mode and Station Mode switch, IP, channels, number or users, SSID.
some camera don't support wifi function, then the wifi unavailable.
Please check the camera manual before you use the wifi function.
Insert your Micro-SD HC card into WiFi CF adapter and you can access high
quality photos and videos sent wirelessly from your camera via Wi-Fi to
your Smartphone or tablet to share.
1.Connect up to 3 devices simultaneously
2.Supports "with the beat-per-view" feature.
3.Supports both Apple Ios & Android devices.
4.WiFi-CF settings: WiFi password,AP Mode and Station Mode switch, IP,
channels, number or users, SSID.
5. Please choose the quality,performance,higher microSDHC Card(recommend
Class 10).
6. Capacity: based on your microSDHC / microSDXC card.
7. SD browse file formats supported:
1) Photo (photo): JPG,PNG,BMP.
2) Video(Video): MP4,AVI,MOV.
3) Music(Music): MP3,WAV.
Note: WiFi-CF can display above file formats,but the ability to play
depends on whether the Wi-Fi device you use can support.
WIFI-CF Default Password: 999999 or 99999999
WIFI-CF Apps Default Username: admin
WIFI-CF Apps Default Password: admin
colour: black+white
Material: ABS
Package Contents:
1*WIFI Adapter Memory Card
Note: WiFi-CF can display above file formats,but the ability to play depends on whether the Wi-Fi device you use can support.
The TF Micro-SD memory card is not included.
Only the above package content, other products are not included.
Note: Light shooting and different displays may cause the color of the item in t
^ Overview
STM32F107 RBT6 + QCA8337 AL3C based router with serial and swd headers
* https://www.st.com/en/microcontrollers/stm32f107rb.html
Mainstream Connectivity line, ARM Cortex-M3 MCU with 128 Kbytes Flash, 72 MHz CPU, Ethernet MAC, CAN and USB 2.0 OTG
^ Firmware
According to https://wiki.mikrotik.com/wiki/SwOS/RB250_RB260#Summary
new RB260GS (CSS106-5G-1S), new RB260GSP(CSS106-1G-4P-1S) supports SwOS v2.0 and newer.
Example working (as of 2018-07-06) url download links which work for CSS106-5G-1S:
https://download2.mikrotik.com/swos2/css106/swos-css1061g4p1s-2.0.bin
https://download2.mikrotik.com/swos2/css106/swos-css1061g4p1s-2.2.bin
.pre
dpavlin@lib10:/lib10/arh-hw/backup/Mikrotik-RB260GS-CSS106-5G-1S/rb260gsp$ md5sum *
bf110ca7e1cd0558cefeacd9e0b62c19 swos-css1061g4p1s-2.0.bin
a491bbf2732937839e6a8222a876cc7a swos-css1061g4p1s-2.2.bin
f098106dfc8ac5ad0fedf0181c68d8de swos-css1061g4p1s-2.3.bin
f4f74f697039a83baa99d37017251805 swos-css1061g4p1s-2.4.bin
90d2ec8571dd9d9aeab1bfbaaa99dea2 swos-css1061g4p1s-2.5.bin
a7f046fc8a12b5ebeb85f9a4bb0dd275 swos-css1061g4p1s-2.6.bin
a1e7adc6ad63e5560156b0f2b6f272ce swos-css1061g4p1s-2.7.bin
.pre
https://mikrotik.com/download (SwitchOS) latest version:
https://download.mikrotik.com/swos2/css106/swos-css106-2.13.bin
^^ version
from web interface
.pre
Firmware
Current Installed Version 2.7 (built at Fri Dec 15 2017 09:42:48 GMT+0100 (CET))
Latest Available Version 2.7 (built at Fri Dec 15 2017 09:42:48 GMT+0100 (CET))
.pre
^ reset
* hold reset while poweron
SwOS v2.x - RB260GS(CSS106-5G-1S) and RB260GSP(CSS106-1G-4P-1S)
The new RB260GS(CSS106-5G-1S) and RB260GSP(CSS106-1G-4P-1S) has built-in backup SwOS firmware which can be loaded in case standard firmware breaks or upgrade fails:
Holding Reset button for few seconds while device is booting resets configuration and loads backup firmware SwOS 2.0p.
After loading backup firmware SwOS 2.0p it is possible to connect to 192.168.88.1 using web browser and install new SwOS firmware.
^^ default ip: 192.168.88.1
.pre
Current Installed Version 2.0p (built at Fri Oct 21 2016 10:18:39 GMT+0200 (CEST))
Latest Available Version 2.7 (built at Fri Dec 15 2017 09:42:48 GMT+0100 (CET))
.pre
After this, router knows that there is new version, but can't download it from http://upgrade.mikrotik.com/swos2/css106/swos-css106-2.7.bin
^ Linux setup
.pre
dpavlin@x230:~$ sudo ifconfig enp0s25 192.168.88.240
wget --http-user=admin --http-password='' 'http://192.168.88.1/!stats.b'
.pre
^^ find on network
https://forum.mikrotik.com/viewtopic.php?t=162881
https://wiki.mikrotik.com/wiki/MAC_access
MNDP frames
sudo apt install mactelnet-client
.pre
dpavlin@klin:~$ mndp
Searching for MikroTik routers... Abort with CTRL+C.
IP MAC-Address Identity (platform version hardware) uptime
192.168.88.1 c4:ad:34:47:12:91 MikroTik (MikroTik 2.7 CSS106-5G-1S) up 113 days 4 hours
10.60.0.1 d4:ca:6d:1:4c:ed ccr (MikroTik 6.46.6 (testing) CCR1036-8G-2S+) up 113 days 4 hours XYIT-4UTW bridge60/sfp2-60
.pre
This page will try to document my advanture in setup of GSM channel on Asterisk
{toc: }
^ Information
* http://code.google.com/p/asterisk-chan-dongle/
* http://www.makhutov.org/svn/chan_datacard/trunk/
* http://wiki.e1550.mobi/
^ Mass-storage switch
http://www.draisberghof.de/usb_modeswitch/
.pre
$ sudo apt-get install usb-modeswitch
.pre
Plugin modem again and you should get a bunch of serial ports:
.pre
[ 5445.108101] usb 2-2: new high speed USB device number 3 using ehci_hcd
[ 5445.242467] usb 2-2: New USB device found, idVendor=12d1, idProduct=1446
[ 5445.242477] usb 2-2: New USB device strings: Mfr=3, Product=2, SerialNumber=0
[ 5445.242484] usb 2-2: Product: HUAWEI Mobile
[ 5445.242489] usb 2-2: Manufacturer: HUAWEI Technology
[ 5445.244981] scsi7 : usb-storage 2-2:1.0
[ 5445.245515] scsi8 : usb-storage 2-2:1.1
[ 5446.017603] usb 2-2: USB disconnect, device number 3
[ 5450.036132] usb 2-2: new high speed USB device number 4 using ehci_hcd
[ 5450.170725] usb 2-2: New USB device found, idVendor=12d1, idProduct=1436
[ 5450.170736] usb 2-2: New USB device strings: Mfr=4, Product=3, SerialNumber=0
[ 5450.170743] usb 2-2: Product: HUAWEI Mobile
[ 5450.170748] usb 2-2: Manufacturer: HUAWEI Technology
[ 5450.175800] scsi14 : usb-storage 2-2:1.5
[ 5450.176793] scsi15 : usb-storage 2-2:1.6
[ 5450.271164] usbcore: registered new interface driver usbserial
[ 5450.271176] USB Serial support registered for generic
[ 5450.271234] usbcore: registered new interface driver usbserial_generic
[ 5450.271236] usbserial: USB Serial Driver core
[ 5450.296230] cdc_ether 2-2:1.1: wwan0: register 'cdc_ether' at usb-0000:00:1d.7-2, Mobile Broadband Network Device, 02:50:f3:00:00:00
[ 5450.296411] usbcore: registered new interface driver cdc_ether
[ 5450.362679] USB Serial support registered for GSM modem (1-port)
[ 5450.362792] option 2-2:1.0: GSM modem (1-port) converter detected
[ 5450.362908] usb 2-2: GSM modem (1-port) converter now attached to ttyUSB0
[ 5450.362928] option 2-2:1.3: GSM modem (1-port) converter detected
[ 5450.362987] usb 2-2: GSM modem (1-port) converter now attached to ttyUSB1
[ 5450.362997] option 2-2:1.4: GSM modem (1-port) converter detected
[ 5450.363051] usb 2-2: GSM modem (1-port) converter now attached to ttyUSB2
[ 5450.363073] usbcore: registered new interface driver option
[ 5450.363074] option: v0.7.2:USB Driver for GSM modems
.pre
^ Devices
^^ Huawei E171
.pre
Found modem : E171
Model : Huawei E171
IMEI : 354807044078459
Serial NR. : 4BA5TA10B2706637
Firmware : 11.126.85.01.143
Compile date / time : Jun 21 2010 20:27:27
Dashboard version : UTPS11.300.05.15.143_MAC11.301.09.01.143
Chipset : Qualcomm MSM6290
Voice feature : disabled
SIM Lock status : unlocked
Wrong codes entered : 0 (unlock attempts left : 10)
.pre
^^ Check if voice is enabled
.pre
ati
Manufacturer: huawei
Model: E171
Revision: 11.126.85.01.143
IMEI: 354807044078459
+GCAP: +CGSM,+DS,+ES
AT^CVOICE?
^CVOICE:0,8000,16,20
.pre
^^ Huawei E1752
http://3g-modem.wetpaint.com/page/Huawei+E1750%2C+E1750C%2C+E1752%2C+E1752C
.pre
Found modem : E1752
Model : Huawei E1752
IMEI : 353145034241600
Serial NR. : O47NAA19A1600110
Firmware : 11.126.13.00.00
Compile date / time : Jul 05 2010 10:16:42
Dashboard version : UTPS11.300.05.22.56_MAC11.300.08.19.56
Chipset : Qualcomm MSM6290
Voice feature : disabled
SIM Lock status : unlocked
Wrong codes entered : 0 (unlock attempts left : 10)
.pre
^^ ZTE K3565-Z
<http://3g-modem.wetpaint.com/page/ZTE+K3565-Z+(Vodafone>)
.pre
Manufacturer: ZTE INCORPORATED
Model: K3565-Z
Revision: BD_P673A2V1.0.0B09
IMEI: 357867029244846
+GCAP: +CGSM,+DS,+ES
OK
AT^CVOICE=?
ERROR
.pre
^^ ZTE MF626
.pre
Manufacturer: ZTE INCORPORATED
Model: MF626
Revision: BD_TMOP673M3V1.0.1B03
IMEI: 355364037442846
+GCAP: +CGSM,+DS,+ES
OK
AT^CVOICE=?
ERROR
.pre
^ Huawei AT commands
.pre
AT^CVOICE=0 Enable Voice
AT^CVOICE=1 Disable Voice
AT^CVOICE=? Check status
=========
AT^U2DIAG=0 – switch the device in modem mode only
AT^U2DIAG=1 – device in modem mode + CD-ROM
AT^U2DIAG=255 – modem mode + CD-ROM + Card Reader
AT^U2DIAG=256 – modem mode + Card Reader
.pre
http://wiki.e1550.mobi/doku.php?id=usage
.pre
AT+CCWA=0,0,1 disable call-waiting
AT+CFUN=1,1 reboot modem
AT^CARDLOCK=”<code>” send unlock code
AT^SYSCFG=13,0,3FFFFFFF,0,3 modem 2G only, automatic search any band, no roaming
AT^SYSCFG=2,0,3FFFFFFF,2,4 Any
AT^SYSCFG=13,1,3FFFFFFF,2,4 2G only
AT^SYSCFG=14,2,3FFFFFFF,2,4 3G only
AT^SYSCFG=2,1,3FFFFFFF,2,4 2G preferred
AT^SYSCFG=2,2,3FFFFFFF,2,4 3G preferred
AT^U2DIAG=0 enable modem function only
ATI get relevant information from modem
ATZ reset modem configuration
AT+CIMI read IMSI
AT+CLCK=“SC”,0,”<pin>” disable PIN verification
.pre
Voice connection
.pre
AT^CVOICE=?
^CVOICE:(0)
OK
AT^CVOICE?
^CVOICE:0,8000,16,20
ATD50463599999
OK
AT^DDSETEX=2
.pre
^ Source code
Test if your modem supports voice capabilities
{fetchrss http://git.rot13.org/?p=huawei.git;a=rss full}
{toc: }
^ Similar boards
^^ B3606
https://github.com/UsrnameTaken/B3606
^^ D3806
I have unit, there is no alternative firmware for this model but there is for:
https://github.com/delboy711/BST900
https://www.falatic.com/index.php/161/minghe-buckboost-converters-handy-if-youre-careful
^ B3603
{image: b3603-swim.jpg}
working keys: https://github.com/nlitsme/b3603/network
https://hackaday.io/project/4362-power-supply-b3603-alternative-firmware
{image: control_pinouts.png}
* http://www.eevblog.com/forum/reviews/b3603-dcdc-buck-converter-mini-review-and-how-the-set-key-could-be-fatal/
* https://github.com/baruch/b3603
* http://www.banggood.com/DC-LED-Digital-Controlled-Step-Down-Driver-Power-Module-p-910096.html
^ Specification
Input voltage: 6V ~ 40V
Output voltage: 0V ~ 36V
Output current: 0A ~ 3A
Conversion efficiency: up to 92%
The output ripple: ≤50mV
Working temperature: -40°C ~ +85°C
Working frequency: 150KHz
Short circuit protection: constant current
Voltage regulation/display resolution: 0.01V
Current regulation/display resolution: 0.001A
The minimum display resolution of power: 0.001W
The minimum display resolution of capacity: 0.001AH
Input reverse connect protection: no, if necessary please install diode
Connection mode: terminals
Size: 66 x 50 x 21mm
Weight: 44g
^ backup existing flash
.pre
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s eeprom -r b3606/eeprom.bin
action = 1Determine EEPROM area
Reading 128 bytes at 0x4000... OK
Bytes received: 128
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s flash -r b3606/flash.bin
action = 1Determine FLASH area
Reading 8192 bytes at 0x8000... OK
Bytes received: 8192
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s ram -r b3606/ram.bin
action = 1Determine RAM area
Reading 1024 bytes at 0x0... OK
Bytes received: 1024
.pre
^ unprotect stm8 using stm8flash
https://github.com/vdudouyt/stm8flash/issues/38#issuecomment-195123081
.pre
$ echo "00" | xxd -r -p >ROP_CLEAR.bin
$ stm8flash -c stlinkv2 -p stm8s103f3 -s opt -w ROP_CLEAR.bin
.pre
^ compile
.pre
pi@rpi2 ~ $ git clone https://github.com/swegener/b3603
Cloning into 'b3603'...
remote: Counting objects: 1109, done.
remote: Total 1109 (delta 0), reused 0 (delta 0), pack-reus
Receiving objects: 100% (1109/1109), 11.04 MiB | 2.90 MiB/s
Resolving deltas: 100% (770/770), done.
Checking connectivity... done.
pi@rpi2 ~/b3603/stm8 $ sudo apt-get install sdcc
pi@rpi2 ~/b3603/stm8 $ make
Code fits the flash, it is 7930
dpavlin@nuc:/nuc/b3603/stm8$ uname -a
Linux nuc 4.4.0-1-amd64 #1 SMP Debian 4.4.6-1 (2016-03-17) x86_64 GNU/Linux
dpavlin@nuc:/nuc/b3603/stm8$ sdcc -v
SDCC : mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/TININative/ds400/hc08/s08/stm8 3.5.0 #9253 (Mar 21 2016) (Linux)
published under GNU General Public License (GPL)
dpavlin@nuc:/nuc/b3603/stm8$ scp b3603.ihx rpi2:stm8flash/
.pre
^ flash
.pre
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -w ./b3603.ihx
action = 2Determine FLASH area
Writing Intel hex file 8160 bytes at 0x8000... Tries exceeded
# unprotect flash
pi@rpi2 ~/stm8flash $ echo "00" | xxd -r -p >ROP_CLEAR.bin
pi@rpi2 ~/stm8flash $ sudo ./stm8flash -c stlinkv2 -p stm8s003f3 -s opt -w ROP_CLEAR.bin
action = 2Determine OPT area
Writing binary file 1 bytes at 0x4800... OK
Bytes written: 1
#
.pre
^ serial
.pre
dpavlin@x200:/x200/stm8$ microcom -p /dev/ttyUSB0 -s 38400
connected to /dev/ttyUSB0
Escape character: Ctrl-\
Type the escape character followed by c to get to the menu or q to quit
B3603 starting: Version 1.0.1
.pre
.pre
pi@rpi2 ~/b3603/stm8 $ cat ~/b3603.sh
#!/bin/sh -x
microcom -s 38400 -p /dev/serial/by-path/platform-3f980000.usb-usb-0\:1.5.1\:1.0-port0
.pre
^ calibrate
.pre
dpavlin@cubieboard:/mnt/nuc/b3603/stm8$ git diff ./calibrate.py
diff --git a/stm8/calibrate.py b/stm8/calibrate.py
index f94f866..313e1f6 100755
--- a/stm8/calibrate.py
+++ b/stm8/calibrate.py
@@ -153,7 +153,8 @@ class Multimeter(object):
return self._sample() != None
def _sample(self):
- p = os.popen('sigrok-cli -d %s:conn=%s --samples 1' % (self.model, self.portname))
+ print('## sigrok-cli -d %s:conn=%s --samples 1' % (self.model, self.portname))
+ p = os.popen('sigrok-cli -d %s:conn=%s --samples 1 -O analog' % (self.model, self.portname))
s = p.read()
p.close()
return float(s.split(' ')[1])
@@ -214,9 +215,9 @@ def calibration_voltage(auto):
return
if auto == True:
- dmm = Multimeter(sys.argv[3], sys.argv[4])
+ dmm = Multimeter(sys.argv[4], sys.argv[5])
if not dmm.open():
- print 'Failed to open serial port to multimeter on serial %s model %s' % (sys.argv[3], sys.argv[4])
+ print 'Failed to open serial port to multimeter on serial %s model %s' % (sys.argv[4], sys.argv[5])
psu.close()
return
dpavlin@cubieboard:/mnt/nuc/b3603/stm8$ ./calibrate.py -a voltage /dev/ttyUSB0 /dev/ttyUSB1 uni-t-ut61e-s
er
OPEN "M: B3603"
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
PSU Input voltage is 11305.0 mV, will use 10 steps between 10 mV and 4000 mV
0 . Setting voltage to 10 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Multimeter samples vary too much, stddev=0.244349, data: [1.2358, 0.8785, 0.6413]
Failed to read stable value, trying again, maybe
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 0 Set voltage 10.000000 mV Read voltage 0.273667 mV PWM 114.0 ADC 132.0 (0.149)
1 . Setting voltage to 409 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 1 Set voltage 409.000000 mV Read voltage 0.403467 mV PWM 185.0 ADC 172.0 (0.377)
2 . Setting voltage to 808 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 2 Set voltage 808.000000 mV Read voltage 0.807800 mV PWM 257.0 ADC 244.0 (0.772)
3 . Setting voltage to 1207 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 3 Set voltage 1207.000000 mV Read voltage 1.212667 mV PWM 329.0 ADC 316.0 (1.179)
4 . Setting voltage to 1606 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 4 Set voltage 1606.000000 mV Read voltage 1.617200 mV PWM 401.0 ADC 387.0 (1.574)
5 . Setting voltage to 2005 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 5 Set voltage 2005.000000 mV Read voltage 2.022333 mV PWM 473.0 ADC 459.0 (1.975)
6 . Setting voltage to 2404 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 6 Set voltage 2404.000000 mV Read voltage 2.425333 mV PWM 545.0 ADC 531.0 (2.376)
7 . Setting voltage to 2803 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 7 Set voltage 2803.000000 mV Read voltage 2.829333 mV PWM 617.0 ADC 603.0 (2.782)
8 . Setting voltage to 3202 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 8 Set voltage 3202.000000 mV Read voltage 3.232000 mV PWM 689.0 ADC 675.0 (3.178)
9 . Setting voltage to 3601 mV
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
## sigrok-cli -d uni-t-ut61e-ser:conn=/dev/ttyUSB1 --samples 1
Step 9 Set voltage 3601.000000 mV Read voltage 3.635667 mV PWM 761.0 ADC 747.0 (3.579)
['OK', '']
ADC
(0.005373500905021045, -0.8923354860819778) 352 58480
['OK', '']
PWM
(179.88709677419354, 185.25806451612908) 11789080 12141072
['OK', '']
.pre
{toc}
^ pinout
{image: nRF24L01_pinout.jpg}
It seems that v2.0 devies are 32k while Internet wants us to beleve that they are 16k (v1.0 maybe?)
^ original firmware output
.pre
[11985.181504] usb 2-2.1: new full-speed USB device number 7 using xhci_hcd
[11985.285687] usb 2-2.1: New USB device found, idVendor=1915, idProduct=002b
[11985.285690] usb 2-2.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[11985.285692] usb 2-2.1: Product: Nordic Semiconductor nRFready Basic Remote Dongle
[11985.285694] usb 2-2.1: Manufacturer: Nordic Semiconductor
[11985.285695] usb 2-2.1: SerialNumber: \xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf\xffffffef\xffffffbf\xffffffbf
[11985.301719] input: Nordic Semiconductor Nordic Semiconductor nRFready Basic Remote Dongle as /devices/pci0000:00/0000:00:14.0/usb2/2-2/2-2.1/2-2.1:1.0/0003:1915:002B.0005/input/input11
[11985.361937] hid-generic 0003:1915:002B.0005: input,hiddev0,hidraw2: USB HID v1.11 Keyboard [Nordic Semiconductor Nordic Semiconductor nRFready Basic Remote Dongle] on usb-0000:00:14.0-2.1/input0
.pre
^ mouse jack tools
https://github.com/BastilleResearch/mousejack
^^ find device address
.pre
dpavlin@nuc:/nuc/nRF24L01/mousejack/nrf-research-firmware/tools$ ./nrf24-scanner.py
[2017-01-07 13:50:59.174] 12 0 65:6F:91:A9:07
[2017-01-07 13:51:07.012] 8 10 65:6F:91:A9:07 00:C2:00:00:F8:FF:FE:00:00:49
[2017-01-07 13:51:15.216] 8 10 65:6F:91:A9:07 00:C2:00:00:17:D0:FF:00:00:58
[2017-01-07 13:51:15.231] 8 0 65:6F:91:A9:07
[2017-01-07 13:51:15.698] 12 0 65:6F:91:A9:07
[2017-01-07 13:51:23.456] 8 10 65:6F:91:A9:07 00:C2:00:00:EB:BF:FF:00:00:95
[2017-01-07 13:51:23.503] 8 10 65:6F:91:A9:07 00:C2:00:00:FF:0F:FF:00:00:31
[2017-01-07 13:51:23.509] 8 0 65:6F:91:A9:07
[2017-01-07 13:51:23.840] 12 0 65:6F:91:A9:07
.pre
^^ sniff
.pre
dpavlin@nuc:/nuc/nRF24L01/mousejack/nrf-research-firmware/tools$ ./nrf24-sniffer.py -c 8 12 -a 65:6F:91:A9:07
[2017-01-07 13:53:34.922] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:34.930] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:34.938] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:34.946] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:34.962] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:34.970] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:34.979] 8 22 65:6F:91:A9:07 00:D3:44:0F:5C:E6:CD:54:B5:71:8C:F9:99:33:00:00:00:00:00:00:00:00
[2017-01-07 13:53:34.986] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:34.994] 8 10 65:6F:91:A9:07 00:4F:00:01:18:00:00:00:00:98
[2017-01-07 13:53:35.125] 8 5 65:6F:91:A9:07 00:40:01:18:A7
[2017-01-07 13:53:35.278] 8 22 65:6F:91:A9:07 00:D3:B0:F4:B3:27:E3:BE:34:72:8C:F9:99:34:00:00:00:00:00:00:00:16
[2017-01-07 13:53:35.285] 8 5 65:6F:91:A9:07 00:40:00:08:B8
[2017-01-07 13:53:35.301] 8 5 65:6F:91:A9:07 00:40:00:08:B8
.pre
^ flashing
https://github.com/BastilleResearch/mousejack/issues/6
https://wiki.bitcraze.io/projects:crazyradio:spi_programming
^^ bus pirate
https://github.com/koolatron/buspirate_nrf24lu1p
| Bus Pirate || nRF24LU1+ |
| 3V3 | -> | VDD |
| AUX | -> | PROG |
| SCK | -> | SCK |
| MOSI | -> | MOSI |
| MISO | -> | MISO |
| CS | -> | CSN |
| GND | -> | GND |
.pre
dpavlin@nuc:/nuc/nRF24L01/buspirate_nrf24lu1p$ ./flasher.pl -device /dev/ttyUSB0 -input ../mousejack/nrf-research-firmware/bin/dongle.bin
.pre
^ bootloader
^^ 512 byte replacement
https://github.com/ahtn/nrf24lu1p-512-bootloader
^^ original bootloader
https://github.com/al177/buspirate_nrf24lu1p
^ Logitech C-U0007
Version with fixed ctrl+c exit bug: https://github.com/cl0udz/mousejack
.pre
dpavlin@x230:/x230/mousejack$ git remote -v
cl0udz https://github.com/cl0udz/mousejack (fetch)
cl0udz https://github.com/cl0udz/mousejack (push)
dpavlin@x230:/x230/mousejack/nrf-research-firmware$ make logitech_install
[Fri Apr 27 22:10:16 2018] usb 1-1.2: new full-speed USB device number 23 using ehci-pci
[Fri Apr 27 22:10:16 2018] usb 1-1.2: New USB device found, idVendor=1915, idProduct=0102
[Fri Apr 27 22:10:16 2018] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[Fri Apr 27 22:10:16 2018] usb 1-1.2: Product: Research Firmware
[Fri Apr 27 22:10:16 2018] usb 1-1.2: Manufacturer: RFStorm
dpavlin@x230:/x230/mousejack/nrf-research-firmware$ ./tools/nrf24-scanner.py
[2018-04-29 14:23:51.370] 5 22 65:6F:91:A9:07 00:D3:D5:D7:4F:76:ED:63:55:70:EC:77:61:0F:00:00:00:00:00:00:00:D4
[2018-04-29 14:23:51.786] 9 5 65:6F:91:A9:07 00:40:00:08:B8
.pre